diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ce68b36d9013..f5dddad093158 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -90,7 +90,6 @@ jobs: --prefix=/usr \ --enable-phpdbg \ --enable-fpm \ - --enable-opcache \ --with-pdo-mysql=mysqlnd \ --with-mysqli=mysqlnd \ --with-pgsql \ @@ -168,7 +167,6 @@ jobs: no_output_timeout: 30m command: | sapi/cli/php run-tests.php \ - -d zend_extension=opcache.so \ -d opcache.enable_cli=1 \ -d opcache.jit_buffer_size=64M \ -d opcache.jit=tracing \ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2bd2f6d94ef9f..973c9d470dc58 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,7 +16,7 @@ /.github @TimWolla /build/gen_stub.php @kocsismate -/ext/bcmath @Girgias @nielsdos @SakiTakamachi +/ext/bcmath @nielsdos @SakiTakamachi /ext/curl @adoy /ext/date @derickr /ext/dba @Girgias diff --git a/.github/actions/apk/action.yml b/.github/actions/apk/action.yml index 039fc64a5491e..da909a367864f 100644 --- a/.github/actions/apk/action.yml +++ b/.github/actions/apk/action.yml @@ -6,6 +6,8 @@ runs: run: | set -x + OPCACHE_TLS_TESTS_DEPS="clang gcc binutils-gold lld" + apk update -q apk add \ util-linux \ @@ -53,4 +55,5 @@ runs: postgresql14-dev \ tzdata \ musl-locales \ - musl-locales-lang + musl-locales-lang \ + $OPCACHE_TLS_TESTS_DEPS diff --git a/.github/actions/apt-x32/action.yml b/.github/actions/apt-x32/action.yml index 39ef1df6c2c8c..14182e7687957 100644 --- a/.github/actions/apt-x32/action.yml +++ b/.github/actions/apt-x32/action.yml @@ -6,6 +6,8 @@ runs: run: | set -x + OPCACHE_TLS_TESTS_DEPS="gcc clang lld" + export DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386 apt-get update -y | true @@ -35,7 +37,6 @@ runs: libssl-dev:i386 \ libwebp-dev:i386 \ libxml2-dev:i386 \ - libxml2-dev:i386 \ libxpm-dev:i386 \ libxslt1-dev:i386 \ firebird-dev:i386 \ @@ -45,4 +46,5 @@ runs: re2c \ unzip \ wget \ - zlib1g-dev:i386 + zlib1g-dev:i386 \ + $OPCACHE_TLS_TESTS_DEPS diff --git a/.github/actions/apt-x64/action.yml b/.github/actions/apt-x64/action.yml index a2ef014c5faa1..7ae0a88ff7557 100644 --- a/.github/actions/apt-x64/action.yml +++ b/.github/actions/apt-x64/action.yml @@ -10,6 +10,8 @@ runs: run: | set -x + OPCACHE_TLS_TESTS_DEPS="gcc clang lld" + export DEBIAN_FRONTEND=noninteractive # Install sudo in Docker for consistent actions @@ -74,4 +76,5 @@ runs: libqdbm-dev \ libjpeg-dev \ libpng-dev \ - libfreetype6-dev + libfreetype6-dev \ + $OPCACHE_TLS_TESTS_DEPS diff --git a/.github/actions/configure-macos/action.yml b/.github/actions/configure-macos/action.yml index b318f22725150..f0af959d21026 100644 --- a/.github/actions/configure-macos/action.yml +++ b/.github/actions/configure-macos/action.yml @@ -11,7 +11,7 @@ runs: set -x BREW_OPT="$(brew --prefix)"/opt export PATH="$BREW_OPT/bison/bin:$PATH" - export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/openssl@1.1/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/openssl/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/curl/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/libffi/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$BREW_OPT/libxml2/lib/pkgconfig" diff --git a/.github/actions/extra-tests/action.yml b/.github/actions/extra-tests/action.yml new file mode 100644 index 0000000000000..0537496064008 --- /dev/null +++ b/.github/actions/extra-tests/action.yml @@ -0,0 +1,7 @@ +name: Extra tests +runs: + using: composite + steps: + - shell: sh + run: | + sapi/cli/php run-extra-tests.php diff --git a/.github/actions/freebsd/action.yml b/.github/actions/freebsd/action.yml index d375a51a6d173..456d88dd1f877 100644 --- a/.github/actions/freebsd/action.yml +++ b/.github/actions/freebsd/action.yml @@ -1,11 +1,18 @@ name: FreeBSD +inputs: + configurationParameters: + default: '' + required: false + runExtraTests: + default: false + required: false runs: using: composite steps: - name: FreeBSD uses: vmactions/freebsd-vm@v1 with: - release: '13.3' + release: '13.5' usesh: true copyback: false # Temporarily disable sqlite, as FreeBSD ships it with disabled double quotes. We'll need to fix our tests. @@ -13,6 +20,8 @@ runs: prepare: | cd $GITHUB_WORKSPACE + OPCACHE_TLS_TESTS_DEPS="gcc" + kldload accf_http pkg install -y \ autoconf \ @@ -37,9 +46,11 @@ runs: webp \ libavif \ `#sqlite3` \ - curl + curl \ + $OPCACHE_TLS_TESTS_DEPS ./buildconf -f + CC=clang CXX=clang++ \ ./configure \ --prefix=/usr/local \ --enable-debug \ @@ -80,7 +91,9 @@ runs: --with-sodium \ --enable-werror \ --with-config-file-path=/etc \ - --with-config-file-scan-dir=/etc/php.d + --with-config-file-scan-dir=/etc/php.d \ + ${{ inputs.configurationParameters }} + gmake -j2 mkdir /etc/php.d gmake install > /dev/null @@ -100,5 +113,8 @@ runs: --offline \ --show-diff \ --show-slow 1000 \ - --set-timeout 120 \ - -d zend_extension=opcache.so + --set-timeout 120 + + if test "${{ inputs.runExtraTests }}" = "true"; then + sapi/cli/php run-extra-tests.php + fi diff --git a/.github/labeler.yml b/.github/labeler.yml index 40ac864fd56c5..b9f0f36e147d4 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -469,7 +469,6 @@ - 'ext/pdo/php_pdo.h' - 'ext/pdo/php_pdo_driver.h' - 'ext/pdo/php_pdo_error.h' - - 'ext/phar/php_phar.h' - 'ext/random/php_random.h' - 'ext/random/php_random_csprng.h' - 'ext/random/php_random_uint128.h' @@ -493,6 +492,7 @@ - 'ext/spl/spl_iterators.h' - 'ext/spl/spl_observer.h' - 'ext/standard/*.h' + - 'ext/uri/*.h' - 'ext/xml/expat_compat.h' - 'ext/xml/php_xml.h' - 'main/*.h' diff --git a/.github/scripts/setup-slapd.sh b/.github/scripts/setup-slapd.sh index fcaa67d0a5f7d..f6b976783c77e 100755 --- a/.github/scripts/setup-slapd.sh +++ b/.github/scripts/setup-slapd.sh @@ -72,6 +72,9 @@ olcTLSCertificateKeyFile: /etc/ldap/ssl/server.key add: olcTLSVerifyClient olcTLSVerifyClient: never - +add: olcTLSProtocolMin +olcTLSProtocolMin: 3.3 +- add: olcAuthzRegexp olcAuthzRegexp: uid=usera,cn=digest-md5,cn=auth cn=usera,dc=my-domain,dc=com - diff --git a/.github/scripts/windows/build.bat b/.github/scripts/windows/build.bat index 65f40fb9462a7..b7beb3a7ef4ba 100644 --- a/.github/scripts/windows/build.bat +++ b/.github/scripts/windows/build.bat @@ -41,7 +41,9 @@ if not exist "%SDK_RUNNER%" ( exit /b 3 ) -cmd /c %SDK_RUNNER% -t .github\scripts\windows\build_task.bat +for /f "delims=" %%T in ('call .github\scripts\windows\find-vs-toolset.bat %PHP_BUILD_CRT%') do set "VS_TOOLSET=%%T" +echo Got VS Toolset %VS_TOOLSET% +cmd /c %SDK_RUNNER% -s %VS_TOOLSET% -t .github\scripts\windows\build_task.bat if %errorlevel% neq 0 exit /b 3 exit /b 0 diff --git a/.github/scripts/windows/find-vs-toolset.bat b/.github/scripts/windows/find-vs-toolset.bat new file mode 100644 index 0000000000000..2d9e68e730318 --- /dev/null +++ b/.github/scripts/windows/find-vs-toolset.bat @@ -0,0 +1,49 @@ +@echo off + +setlocal enabledelayedexpansion + +if "%~1"=="" ( + echo ERROR: Usage: %~nx0 [vc14^|vc15^|vs16^|vs17] + exit /b 1 +) + +set "toolsets_vc14=14.0" +set "toolsets_vc15=" +set "toolsets_vs16=" +set "toolsets_vs17=" + + +for /f "usebackq tokens=*" %%I in (`vswhere.exe -latest -find "VC\Tools\MSVC"`) do set "MSVCDIR=%%I" + +if not defined MSVCDIR ( + echo ERROR: could not locate VC\Tools\MSVC + exit /b 1 +) + +for /f "delims=" %%D in ('dir /b /ad "%MSVCDIR%"') do ( + for /f "tokens=1,2 delims=." %%A in ("%%D") do ( + set "maj=%%A" & set "min=%%B" + if "!maj!"=="14" ( + if !min! LEQ 9 ( + set "toolsets_vc14=%%D" + ) else if !min! LEQ 19 ( + set "toolsets_vc15=%%D" + ) else if !min! LEQ 29 ( + set "toolsets_vs16=%%D" + ) else ( + set "toolsets_vs17=%%D" + ) + ) + ) +) + +set "KEY=%~1" +set "VAR=toolsets_%KEY%" +call set "RESULT=%%%VAR%%%" +if defined RESULT ( + echo %RESULT% + exit /b 0 +) else ( + echo ERROR: no toolset found for %KEY% + exit /b 1 +) diff --git a/.github/scripts/windows/test.bat b/.github/scripts/windows/test.bat index 1a24564697219..b8cc501e0cf3f 100644 --- a/.github/scripts/windows/test.bat +++ b/.github/scripts/windows/test.bat @@ -9,7 +9,8 @@ if not exist "%SDK_RUNNER%" ( exit /b 3 ) -cmd /c %SDK_RUNNER% -t .github\scripts\windows\test_task.bat +for /f "delims=" %%T in ('call .github\scripts\windows\find-vs-toolset.bat %PHP_BUILD_CRT%') do set "VS_TOOLSET=%%T" +cmd /c %SDK_RUNNER% -s %VS_TOOLSET% -t .github\scripts\windows\test_task.bat if %errorlevel% neq 0 exit /b 3 exit /b 0 diff --git a/.github/scripts/windows/test_task.bat b/.github/scripts/windows/test_task.bat index 43e7763e70294..84ce0acc72216 100644 --- a/.github/scripts/windows/test_task.bat +++ b/.github/scripts/windows/test_task.bat @@ -128,7 +128,7 @@ mkdir %PHP_BUILD_DIR%\test_file_cache rem generate php.ini echo extension_dir=%PHP_BUILD_DIR% > %PHP_BUILD_DIR%\php.ini echo opcache.file_cache=%PHP_BUILD_DIR%\test_file_cache >> %PHP_BUILD_DIR%\php.ini -if "%OPCACHE%" equ "1" echo zend_extension=php_opcache.dll >> %PHP_BUILD_DIR%\php.ini +echo opcache.record_warnings=1 >> %PHP_BUILD_DIR%\php.ini rem work-around for some spawned PHP processes requiring OpenSSL and sockets echo extension=php_openssl.dll >> %PHP_BUILD_DIR%\php.ini echo extension=php_sockets.dll >> %PHP_BUILD_DIR%\php.ini diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6ae972d92e49c..3e59990742cbe 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,7 +17,7 @@ jobs: if: github.repository == 'php/php-src' steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install dependencies run: pip install -r docs/requirements.txt - name: Check formatting diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1b1532af7f799..41c48c9a936d5 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -23,12 +23,18 @@ on: run_macos_arm64: required: true type: boolean + run_freebsd_zts: + required: true + type: boolean ubuntu_version: required: true type: string windows_version: required: true type: string + vs_crt_version: + required: true + type: string skip_laravel: required: true type: boolean @@ -38,6 +44,9 @@ on: skip_wordpress: required: true type: boolean + variation_enable_zend_max_execution_timers: + required: true + type: boolean permissions: contents: read jobs: @@ -48,7 +57,7 @@ jobs: runs-on: [self-hosted, gentoo, ppc64] steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: System info @@ -79,6 +88,8 @@ jobs: with: runTestsParameters: >- --asan -x + - name: Extra tests + uses: ./.github/actions/extra-tests ALPINE: if: inputs.run_alpine name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS @@ -87,7 +98,7 @@ jobs: image: 'alpine:3.20.1' steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: apk @@ -126,8 +137,9 @@ jobs: jitType: tracing runTestsParameters: >- --asan -x - -d zend_extension=opcache.so -d opcache.enable_cli=1 + - name: Extra tests + uses: ./.github/actions/extra-tests - name: Notify Slack if: failure() uses: ./.github/actions/notify-slack @@ -189,6 +201,7 @@ jobs: zts: true configuration_parameters: >- CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE" + ${{ inputs.variation_enable_zend_max_execution_timers && '--enable-zend-max-execution-timers' || '' }} run_tests_parameters: -d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0 timeout_minutes: 360 test_function_jit: true @@ -197,7 +210,7 @@ jobs: runs-on: ubuntu-${{ matrix.asan && inputs.asan_ubuntu_version || inputs.ubuntu_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: Create MSSQL container @@ -240,14 +253,12 @@ jobs: jitType: tracing runTestsParameters: >- ${{ matrix.run_tests_parameters }} - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Test OpCache uses: ./.github/actions/test-linux with: runTestsParameters: >- ${{ matrix.run_tests_parameters }} - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Test Function JIT # ASAN frequently timeouts. Each test run takes ~90 minutes, we can @@ -258,8 +269,9 @@ jobs: jitType: function runTestsParameters: >- ${{ matrix.run_tests_parameters }} - -d zend_extension=opcache.so -d opcache.enable_cli=1 + - name: Extra tests + uses: ./.github/actions/extra-tests - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - name: Notify Slack @@ -298,7 +310,7 @@ jobs: FIREBIRD_PASSWORD: test steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: apt @@ -332,14 +344,12 @@ jobs: jitType: tracing runTestsParameters: >- ${{ matrix.run_tests_parameters }} - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Test OpCache uses: ./.github/actions/test-linux with: runTestsParameters: >- ${{ matrix.run_tests_parameters }} - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Test Function JIT uses: ./.github/actions/test-linux @@ -347,8 +357,9 @@ jobs: jitType: function runTestsParameters: >- ${{ matrix.run_tests_parameters }} - -d zend_extension=opcache.so -d opcache.enable_cli=1 + - name: Extra tests + uses: ./.github/actions/extra-tests - name: Notify Slack if: failure() uses: ./.github/actions/notify-slack @@ -367,7 +378,7 @@ jobs: runs-on: macos-${{ matrix.os }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: brew @@ -392,13 +403,11 @@ jobs: with: jitType: tracing runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Test OpCache uses: ./.github/actions/test-macos with: runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Test Function JIT if: matrix.os != '14' || !matrix.zts @@ -406,8 +415,9 @@ jobs: with: jitType: function runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 + - name: Extra tests + uses: ./.github/actions/extra-tests - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - name: Notify Slack @@ -443,7 +453,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: Create MSSQL container @@ -468,9 +478,8 @@ jobs: with: jitType: tracing runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 if: ${{ !cancelled() }} with: fail_ci_if_error: true @@ -497,7 +506,7 @@ jobs: USE_TRACKED_ALLOC: 1 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: apt @@ -522,7 +531,6 @@ jobs: - name: Enable Opcache run: | echo memory_limit=-1 >> /etc/php.d/opcache.ini - echo zend_extension=opcache.so > /etc/php.d/opcache.ini echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini echo opcache.enable=1 >> /etc/php.d/opcache.ini echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini @@ -549,14 +557,17 @@ jobs: repositories="amp cache dns file http parallel parser pipeline process serialization socket sync websocket-client websocket-server" X=0 for repository in $repositories; do - printf "Testing amp/%s\n" "$repository" + echo "::group::$repository" git clone "https://github.com/amphp/$repository.git" "amphp-$repository" --depth 1 cd "amphp-$repository" git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ + EXIT_CODE=0 vendor/bin/phpunit || EXIT_CODE=$? + echo -e "\n::endgroup::" if [ ${EXIT_CODE:-0} -gt 128 ]; then X=1; + echo "Failed" fi cd .. done @@ -580,14 +591,17 @@ jobs: repositories="async cache child-process datagram dns event-loop promise promise-stream promise-timer stream" X=0 for repository in $repositories; do - printf "Testing reactphp/%s\n" "$repository" + echo "::group::$repository" git clone "https://github.com/reactphp/$repository.git" "reactphp-$repository" --depth 1 cd "reactphp-$repository" git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ + EXIT_CODE=0 vendor/bin/phpunit || EXIT_CODE=$? + echo -e "\n::endgroup::" if [ $[EXIT_CODE:-0} -gt 128 ]; then X=1; + echo "Failed" fi cd .. done @@ -612,15 +626,19 @@ jobs: php /usr/bin/composer install --no-progress --ignore-platform-req=php+ php ./phpunit install # Test causes a heap-buffer-overflow but I cannot reproduce it locally... - php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "/** @group skip */\n public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);' + php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);' # Buggy FFI test in Symfony, see https://github.com/symfony/symfony/issues/47668 - php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("public function testCastNonTrailingCharPointer()", "/** @group skip */\n public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);' + php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("public function testCastNonTrailingCharPointer()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);' export SYMFONY_DEPRECATIONS_HELPER=max[total]=999 X=0 for component in $(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n'); do - php ./phpunit $component --exclude-group tty,benchmark,intl-data,transient --exclude-group skip || EXIT_CODE=$? + echo "::group::$component" + EXIT_CODE=0 + php ./phpunit $component --exclude-group tty --exclude-group benchmark --exclude-group intl-data --exclude-group transient --exclude-group skip || EXIT_CODE=$? + echo -e "\n::endgroup::" if [ ${EXIT_CODE:-0} -gt 128 ]; then X=1; + echo "Failed" fi done exit $X @@ -691,7 +709,7 @@ jobs: runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: Create MSSQL container @@ -713,21 +731,18 @@ jobs: uses: ./.github/actions/test-linux with: runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 --file-cache-prime - name: Test File Cache (prime shm, use shm) uses: ./.github/actions/test-linux with: runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 --file-cache-use - name: Test File Cache (prime shm, use file) uses: ./.github/actions/test-linux with: runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 --file-cache-use -d opcache.file_cache_only=1 @@ -735,7 +750,6 @@ jobs: uses: ./.github/actions/test-linux with: runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 --file-cache-prime -d opcache.file_cache_only=1 @@ -743,7 +757,6 @@ jobs: uses: ./.github/actions/test-linux with: runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 --file-cache-use -d opcache.file_cache_only=1 @@ -759,7 +772,7 @@ jobs: runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: apt @@ -837,7 +850,6 @@ jobs: with: runTestsParameters: >- --msan - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files @@ -851,7 +863,7 @@ jobs: runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: apt @@ -901,38 +913,38 @@ jobs: CXX: ccache g++ steps: - name: git checkout PHP - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: path: php ref: ${{ inputs.branch }} - name: git checkout apcu - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: krakjoe/apcu path: apcu - name: git checkout imagick - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: Imagick/imagick path: imagick - name: git checkout memcached - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: php-memcached-dev/php-memcached path: memcached - name: git checkout redis - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: phpredis/phpredis path: redis - name: git checkout xdebug if: false - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: xdebug/xdebug path: xdebug - name: git checkout yaml - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: php/pecl-file_formats-yaml path: yaml @@ -1031,7 +1043,7 @@ jobs: PHP_BUILD_OBJ_DIR: C:\obj PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk PHP_BUILD_SDK_BRANCH: php-sdk-2.3.0 - PHP_BUILD_CRT: ${{ inputs.windows_version == '2022' && 'vs17' || 'vs16' }} + PHP_BUILD_CRT: ${{ inputs.vs_crt_version }} PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }} THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}" INTRINSICS: "${{ matrix.zts && 'AVX2' || '' }}" @@ -1042,7 +1054,7 @@ jobs: - name: git config run: git config --global core.autocrlf false && git config --global core.eol lf - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: Setup @@ -1052,12 +1064,23 @@ jobs: - name: Test run: .github/scripts/windows/test.bat FREEBSD: - name: FREEBSD + strategy: + fail-fast: false + matrix: + zts: [true, false] + exclude: + - zts: ${{ !inputs.run_freebsd_zts && true || '*never*' }} + name: "FREEBSD_${{ matrix.zts && 'ZTS' || 'NTS' }}" runs-on: ubuntu-latest + timeout-minutes: 50 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} - name: FreeBSD uses: ./.github/actions/freebsd + with: + configurationParameters: >- + --${{ matrix.zts && 'enable' || 'disable' }}-zts + runExtraTests: true diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 2f82179b90ec6..47001d85bb3a2 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -82,7 +82,7 @@ jobs: timeout-minutes: 50 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: apt uses: ./.github/actions/apt-x64 - name: System info @@ -112,6 +112,7 @@ jobs: with: configurationParameters: >- --${{ matrix.debug && 'enable' || 'disable' }}-debug + ${{ matrix.debug && 'CXXFLAGS="-D_GLIBCXX_ASSERTIONS"' || '' }} --${{ matrix.zts && 'enable' || 'disable' }}-zts ${{ matrix.asan && 'CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" CC=clang CXX=clang++' || '' }} skipSlow: ${{ matrix.asan }} @@ -130,7 +131,6 @@ jobs: with: jitType: tracing runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 ${{ matrix.asan && '--asan -x' || '' }} - name: Verify generated files are up to date @@ -167,7 +167,7 @@ jobs: FIREBIRD_PASSWORD: test steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: apt uses: ./.github/actions/apt-x32 - name: ccache @@ -190,7 +190,6 @@ jobs: with: jitType: tracing runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 MACOS_DEBUG_NTS: if: github.repository == 'php/php-src' || github.event_name == 'pull_request' @@ -198,14 +197,14 @@ jobs: fail-fast: false matrix: include: - - os: 14 + - os: 15 arch: ARM64 name: MACOS_${{ matrix.arch }}_DEBUG_NTS runs-on: macos-${{ matrix.os }} timeout-minutes: 50 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: brew uses: ./.github/actions/brew - name: ccache @@ -229,7 +228,6 @@ jobs: with: jitType: tracing runTestsParameters: >- - -d zend_extension=opcache.so -d opcache.enable_cli=1 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files @@ -253,7 +251,7 @@ jobs: - name: git config run: git config --global core.autocrlf false && git config --global core.eol lf - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup uses: ./.github/actions/setup-windows - name: Build @@ -267,7 +265,7 @@ jobs: timeout-minutes: 50 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 # ASLR can cause a lot of noise due to missed sse opportunities for memcpy @@ -299,7 +297,6 @@ jobs: ./configure \ --disable-debug \ --enable-mbstring \ - --enable-opcache \ --enable-option-checking=fatal \ --enable-sockets \ --enable-werror \ @@ -319,7 +316,6 @@ jobs: sudo mkdir -p /etc/php.d sudo chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini - echo zend_extension=opcache.so >> /etc/php.d/opcache.ini echo opcache.enable=1 >> /etc/php.d/opcache.ini echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini - name: Setup @@ -331,7 +327,7 @@ jobs: mysql -uroot -proot -e "CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'wordpress'; FLUSH PRIVILEGES;" mysql -uroot -proot -e "GRANT ALL PRIVILEGES ON *.* TO 'wordpress'@'localhost' WITH GRANT OPTION;" - name: git checkout benchmarking-data - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: php/benchmarking-data ssh-key: ${{ secrets.BENCHMARKING_DATA_DEPLOY_KEY }} @@ -371,8 +367,9 @@ jobs: if: github.repository == 'php/php-src' || github.event_name == 'pull_request' name: FREEBSD runs-on: ubuntu-latest + timeout-minutes: 50 steps: - name: git checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: FreeBSD uses: ./.github/actions/freebsd diff --git a/.github/workflows/real-time-benchmark.yml b/.github/workflows/real-time-benchmark.yml index 9e1fa9fdbe6a2..539e9768f4ac1 100644 --- a/.github/workflows/real-time-benchmark.yml +++ b/.github/workflows/real-time-benchmark.yml @@ -2,14 +2,109 @@ name: Real-time Benchmark on: schedule: - cron: "30 0 * * *" + workflow_dispatch: + inputs: + pull_request: + description: 'PR number that is going to be benchmarked (e.g. "1234")' + required: true + type: number + jit: + description: 'Whether JIT is benchmarked' + required: false + default: "0" + type: choice + options: + - "0" + - "1" + instruction_count: + description: 'Whether Valgrind instruction count should be measured' + required: true + default: "0" + type: choice + options: + - "0" + - "1" + opcache: + description: 'Whether opcache is enabled for the benchmarked commit' + required: true + default: "1" + type: choice + options: + - "0" + - "1" + - "2" + baseline_opcache: + description: 'Whether opcache is enabled for the baseline commit' + required: true + default: "1" + type: choice + options: + - "0" + - "1" + - "2" + run_micro_bench: + description: 'Whether to run the micro_bench.php test' + required: true + default: "0" + type: choice + options: + - "0" + - "1" permissions: contents: read + pull-requests: write +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false jobs: REAL_TIME_BENCHMARK: name: REAL_TIME_BENCHMARK - if: github.repository == 'php/php-src' + if: github.repository == 'php/php-src' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-22.04 + env: + REPOSITORY: ${{ github.repository }} + BRANCH: "master" + COMMIT: ${{ github.sha }} + BASELINE_COMMIT: "d5f6e56610c729710073350af318c4ea1b292cfe" + ID: "master" + OPCACHE: "1" + BASELINE_OPCACHE: "2" + JIT: "1" + INSTRUCTION_COUNT: "1" + RUN_MICRO_BENCH: "0" + YEAR: "" steps: + - name: Setup benchmark environment + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + YEAR="$(date '+%Y')" + echo "YEAR=$YEAR" >> $GITHUB_ENV + + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + PR_INFO=$(gh pr view ${{ inputs.pull_request }} --json headRepositoryOwner,headRepository,headRefName,headRefOid,baseRefOid --repo ${{ github.repository }} | jq -r '.headRepositoryOwner.login, .headRepository.name, .headRefName, .headRefOid, .baseRefOid') + + REPOSITORY="$(echo "$PR_INFO" | sed -n '1p')/$(echo "$PR_INFO" | sed -n '2p')" + echo "REPOSITORY=$REPOSITORY" >> $GITHUB_ENV + + BRANCH=$(echo "$PR_INFO" | sed -n '3p') + echo "BRANCH=$BRANCH" >> $GITHUB_ENV + + COMMIT=$(echo "$PR_INFO" | sed -n '4p') + echo "COMMIT=$COMMIT" >> $GITHUB_ENV + + BASELINE_COMMIT=$(echo "$PR_INFO" | sed -n '5p') + echo "BASELINE_COMMIT=$BASELINE_COMMIT" >> $GITHUB_ENV + + echo "ID=benchmarked" >> $GITHUB_ENV + + echo "OPCACHE=${{ inputs.opcache }}" >> $GITHUB_ENV + echo "BASELINE_OPCACHE=${{ inputs.baseline_opcache }}" >> $GITHUB_ENV + echo "JIT=${{ inputs.jit }}" >> $GITHUB_ENV + echo "INSTRUCTION_COUNT=${{ inputs.instruction_count }}" >> $GITHUB_ENV + echo "RUN_MICRO_BENCH=${{ inputs.run_micro_bench }}" >> $GITHUB_ENV + fi + - name: Install dependencies run: | set -ex @@ -23,85 +118,161 @@ jobs: sudo apt-get update -y sudo apt-get install -y terraform=1.5.7-* - name: Checkout benchmark suite - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: 'kocsismate/php-version-benchmarks' ref: 'main' fetch-depth: 1 path: 'php-version-benchmarks' - - name: Checkout php-src - uses: actions/checkout@v4 + - name: Checkout php-src (benchmarked version) + uses: actions/checkout@v5 with: - repository: 'php/php-src' - ref: '${{ github.sha }}' + repository: '${{ env.REPOSITORY }}' + ref: '${{ env.COMMIT }}' fetch-depth: 100 - path: 'php-version-benchmarks/tmp/php_master' + path: 'php-version-benchmarks/tmp/php_${{ env.ID }}' + - name: Checkout php-src (baseline version) + uses: actions/checkout@v5 + with: + repository: '${{ env.REPOSITORY }}' + ref: '${{ env.BASELINE_COMMIT }}' + fetch-depth: 100 + path: 'php-version-benchmarks/tmp/php_baseline' - name: Setup benchmark results run: | git config --global user.name "Benchmark" git config --global user.email "benchmark@php.net" - + rm -rf ./php-version-benchmarks/docs/results - name: Checkout benchmark data - uses: actions/checkout@v4 + if: github.event_name != 'workflow_dispatch' + uses: actions/checkout@v5 with: repository: php/real-time-benchmark-data ssh-key: ${{ secrets.PHP_VERSION_BENCHMARK_RESULTS_DEPLOY_KEY }} path: 'php-version-benchmarks/docs/results' - - name: Set benchmark config + - name: Setup infra config run: | set -e - # Set infrastructure config cp ./php-version-benchmarks/config/infra/aws/x86_64-metal.ini.dist ./php-version-benchmarks/config/infra/aws/x86_64-metal.ini ESCAPED_DOCKER_REGISTRY=$(printf '%s\n' "${{ secrets.PHP_VERSION_BENCHMARK_DOCKER_REGISTRY }}" | sed -e 's/[\/&]/\\&/g') sed -i "s/INFRA_DOCKER_REGISTRY=public.ecr.aws\/abcdefgh/INFRA_DOCKER_REGISTRY=$ESCAPED_DOCKER_REGISTRY/g" ./php-version-benchmarks/config/infra/aws/x86_64-metal.ini + sed -i "s/INFRA_MEASURE_INSTRUCTION_COUNT=0/INFRA_MEASURE_INSTRUCTION_COUNT=${{ env.INSTRUCTION_COUNT }}/g" ./php-version-benchmarks/config/infra/aws/x86_64-metal.ini cp ./php-version-benchmarks/build/infrastructure/config/aws.tfvars.dist ./php-version-benchmarks/build/infrastructure/config/aws.tfvars sed -i 's/access_key = ""/access_key = "${{ secrets.PHP_VERSION_BENCHMARK_AWS_ACCESS_KEY }}"/g' ./php-version-benchmarks/build/infrastructure/config/aws.tfvars sed -i 's/secret_key = ""/secret_key = "${{ secrets.PHP_VERSION_BENCHMARK_AWS_SECRET_KEY }}"/g' ./php-version-benchmarks/build/infrastructure/config/aws.tfvars + sed -i 's/github_token = ""/github_token = "${{ secrets.GITHUB_TOKEN }}"/g' ./php-version-benchmarks/build/infrastructure/config/aws.tfvars + - name: Setup PHP config - baseline PHP version + run: | + set -e - YEAR="$(date '+%Y')" - DATABASE="./php-version-benchmarks/docs/results/$YEAR/database.tsv" + BASELINE_SHORT_SHA="$(echo "${{ env.BASELINE_COMMIT }}" | cut -c1-4)" + + cat << EOF > ./php-version-benchmarks/config/php/baseline.ini + PHP_NAME="PHP - baseline@$BASELINE_SHORT_SHA" + PHP_ID=php_baseline + + PHP_REPO=https://github.com/${{ env.REPOSITORY }}.git + PHP_BRANCH=${{ env.BRANCH }} + PHP_COMMIT=${{ env.BASELINE_COMMIT }} + + PHP_OPCACHE=${{ env.BASELINE_OPCACHE }} + PHP_JIT=0 + EOF + - name: Setup PHP config - baseline PHP version with JIT + if: github.event_name == 'workflow_dispatch' && inputs.jit == '1' + run: | + set -e + + BASELINE_SHORT_SHA="$(echo "${{ env.BASELINE_COMMIT }}" | cut -c1-4)" + + cat << EOF > ./php-version-benchmarks/config/php/baseline_jit.ini + PHP_NAME="PHP - baseline@$BASELINE_SHORT_SHA (JIT)" + PHP_ID=php_baseline_jit + + PHP_REPO=https://github.com/${{ env.REPOSITORY }}.git + PHP_BRANCH=${{ env.BRANCH }} + PHP_COMMIT=${{ env.BASELINE_COMMIT }} + + PHP_OPCACHE=${{ env.BASELINE_OPCACHE }} + PHP_JIT=${{ env.JIT }} + EOF + + git clone ./php-version-benchmarks/tmp/php_baseline/ ./php-version-benchmarks/tmp/php_baseline_jit + - name: Setup PHP config - previous PHP version + if: github.event_name != 'workflow_dispatch' + run: | + set -e + + DATABASE="./php-version-benchmarks/docs/results/${{ env.YEAR }}/database.tsv" if [ -f "$DATABASE" ]; then LAST_RESULT_SHA="$(tail -n 2 "$DATABASE" | head -n 1 | cut -f 6)" else YESTERDAY="$(date -d "-2 day 23:59:59" '+%Y-%m-%d %H:%M:%S')" - LAST_RESULT_SHA="$(cd ./php-version-benchmarks/tmp/php_master/ && git --no-pager log --until="$YESTERDAY" -n 1 --pretty='%H')" + LAST_RESULT_SHA="$(cd ./php-version-benchmarks/tmp/php_${{ env.ID }}/ && git --no-pager log --until="$YESTERDAY" -n 1 --pretty='%H')" fi - BASELINE_SHA="d5f6e56610c729710073350af318c4ea1b292cfe" - BASELINE_SHORT_SHA="$(echo "$BASELINE_SHA" | cut -c1-4)" + cat << EOF > ./php-version-benchmarks/config/php/previous.ini + PHP_NAME="PHP - previous ${{ env.BRANCH }}" + PHP_ID=php_previous + + PHP_REPO=https://github.com/${{ env.REPOSITORY }}.git + PHP_BRANCH=${{ env.BRANCH }} + PHP_COMMIT=$LAST_RESULT_SHA + + PHP_OPCACHE=1 + PHP_JIT=0 + EOF + - name: Setup PHP config - benchmarked PHP version + run: | + set -e + + cat << EOF > ./php-version-benchmarks/config/php/this.ini + PHP_NAME="PHP - ${{ env.BRANCH }}" + PHP_ID=php_${{ env.ID }} + + PHP_REPO=https://github.com/${{ env.REPOSITORY }}.git + PHP_BRANCH=${{ env.BRANCH }} + PHP_COMMIT=${{ env.COMMIT }} - # Set config for the baseline PHP version - cp ./php-version-benchmarks/config/php/master.ini.dist ./php-version-benchmarks/config/php/master_baseline.ini - sed -i 's/PHP_NAME="PHP - master"/PHP_NAME="PHP - baseline@'"$BASELINE_SHORT_SHA"'"/g' ./php-version-benchmarks/config/php/master_baseline.ini - sed -i "s/PHP_ID=php_master/PHP_ID=php_master_baseline/g" ./php-version-benchmarks/config/php/master_baseline.ini - sed -i "s/PHP_COMMIT=/PHP_COMMIT=$BASELINE_SHA/g" ./php-version-benchmarks/config/php/master_baseline.ini + PHP_OPCACHE=${{ env.OPCACHE }} + PHP_JIT=0 + EOF + - name: Setup PHP config - benchmarked PHP version with JIT + if: env.JIT == '1' + run: | + set -e - # Set config for the previous PHP version - cp ./php-version-benchmarks/config/php/master.ini.dist ./php-version-benchmarks/config/php/master_last.ini - sed -i 's/PHP_NAME="PHP - master"/PHP_NAME="PHP - previous master"/g' ./php-version-benchmarks/config/php/master_last.ini - sed -i "s/PHP_ID=php_master/PHP_ID=php_master_previous/g" ./php-version-benchmarks/config/php/master_last.ini - sed -i "s/PHP_COMMIT=/PHP_COMMIT=$LAST_RESULT_SHA/g" ./php-version-benchmarks/config/php/master_last.ini + cat << EOF > ./php-version-benchmarks/config/php/this_jit.ini + PHP_NAME="PHP - ${{ env.BRANCH }} (JIT)" + PHP_ID=php_${{ env.ID }}_jit - # Set config for the current PHP version - cp ./php-version-benchmarks/config/php/master.ini.dist ./php-version-benchmarks/config/php/master_now.ini - sed -i "s/PHP_COMMIT=/PHP_COMMIT=${{ github.sha }}/g" ./php-version-benchmarks/config/php/master_now.ini + PHP_REPO=https://github.com/${{ env.REPOSITORY }}.git + PHP_BRANCH=${{ env.BRANCH }} + PHP_COMMIT=${{ env.COMMIT }} - # Set config for current PHP version with JIT - git clone ./php-version-benchmarks/tmp/php_master/ ./php-version-benchmarks/tmp/php_master_jit - cp ./php-version-benchmarks/config/php/master_jit.ini.dist ./php-version-benchmarks/config/php/master_now_jit.ini - sed -i "s/PHP_COMMIT=/PHP_COMMIT=${{ github.sha }}/g" ./php-version-benchmarks/config/php/master_now_jit.ini + PHP_OPCACHE=${{ env.OPCACHE }} + PHP_JIT=${{ env.JIT }} + EOF + + git clone ./php-version-benchmarks/tmp/php_${{ env.ID }}/ ./php-version-benchmarks/tmp/php_${{ env.ID }}_jit + - name: Setup test config + run: | + set -e - # Set test configs cp ./php-version-benchmarks/config/test/1_laravel.ini.dist ./php-version-benchmarks/config/test/1_laravel.ini cp ./php-version-benchmarks/config/test/2_symfony_main.ini.dist ./php-version-benchmarks/config/test/2_symfony_main.ini cp ./php-version-benchmarks/config/test/4_wordpress.ini.dist ./php-version-benchmarks/config/test/4_wordpress.ini cp ./php-version-benchmarks/config/test/5_bench.php.ini.dist ./php-version-benchmarks/config/test/5_bench.php.ini - cp ./php-version-benchmarks/config/test/6_micro_bench.php.ini.dist ./php-version-benchmarks/config/test/6_micro_bench.php.ini + + if [ "${{ env.RUN_MICRO_BENCH }}" -eq "1" ]; then + cp ./php-version-benchmarks/config/test/6_micro_bench.php.ini.dist ./php-version-benchmarks/config/test/6_micro_bench.php.ini + fi - name: Run benchmark run: ./php-version-benchmarks/benchmark.sh run aws - name: Store results + if: github.repository == 'php/php-src' && github.event_name != 'workflow_dispatch' run: | set -ex @@ -117,6 +288,21 @@ jobs: fi git commit -m "Add result for ${{ github.repository }}@${{ github.sha }}" git push + - name: Upload artifact + if: github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: results + path: ./php-version-benchmarks/docs/results/${{ env.YEAR }} + retention-days: 30 + - name: Comment results + if: github.event_name == 'workflow_dispatch' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + cd ./php-version-benchmarks/tmp/php_${{ env.ID }} + NEWEST_RESULT_DIRECTORY=$(ls -td ${{ github.workspace }}/php-version-benchmarks/docs/results/${{ env.YEAR }}/*/ | head -1) + gh pr comment ${{ inputs.pull_request }} --body-file "${NEWEST_RESULT_DIRECTORY}result.md" --repo ${{ github.repository }} - name: Cleanup if: always() run: | diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index a98bb39ba0d92..b70b026eced07 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -13,7 +13,7 @@ jobs: outputs: branches: ${{ steps.set-matrix.outputs.branches }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: # Set fetch-depth to 0 to clone the full repository # including all branches. This is required to find @@ -55,11 +55,14 @@ jobs: run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} run_linux_ppc64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} + run_freebsd_zts: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) || matrix.branch.version[0] >= 9 }} ubuntu_version: ${{ (((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 5) || matrix.branch.version[0] >= 9) && '24.04') || '22.04' }} - windows_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '2022' || '2019' }} + windows_version: '2022' + vs_crt_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) && 'vs17') || 'vs16' }} skip_laravel: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} skip_symfony: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} skip_wordpress: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} + variation_enable_zend_max_execution_timers: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) || matrix.branch.version[0] >= 9 }} secrets: inherit diff --git a/.gitignore b/.gitignore index 3c4566ed663c3..b76b5a787caa0 100644 --- a/.gitignore +++ b/.gitignore @@ -131,6 +131,7 @@ config.h.in /sapi/cgi/php-cgi /sapi/fpm/php-fpm /sapi/phpdbg/phpdbg +/sapi/fuzzer/php-fuzz-* /scripts/php-config /scripts/phpize php @@ -294,6 +295,13 @@ tmp-php.ini /junit.out.xml /.ccache/ +# ------------------------------------------------------------------------------ +# Editor configuration directories +# ------------------------------------------------------------------------------ +/.idea/ +/.vscode/ +/.zed/ + # ------------------------------------------------------------------------------ # Additional test build files # ------------------------------------------------------------------------------ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a91545fa9bd79..31d893e8d42a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,7 @@ had several contributions accepted, commit privileges are often quickly granted. * [What happens when your contribution is applied?](#what-happens-when-your-contribution-is-applied) * [Git commit rules](#git-commit-rules) * [Copyright and license headers](#copyright-and-license-headers) +* [NEWS file](#news) ## Pull requests @@ -385,11 +386,8 @@ The next few rules are more of a technical nature: later branches) an empty merge should be done. 2. All news updates intended for public viewing, such as new features, bug - fixes, improvements, etc., should go into the NEWS file of *any stable - release* version with the given change. In other words, news about a bug fix - which went into PHP-5.4, PHP-5.5 and master should be noted in both - PHP-5.4/NEWS and PHP-5.5/NEWS but not master, which is not a public released - version yet. + fixes, improvements, etc., should go into the NEWS file. See the section on + [NEWS](#news) below. 3. Do not commit multiple files and dump all messages in one commit. If you modified several unrelated files, commit each group separately and provide a @@ -422,14 +420,13 @@ An Example from the git project (commit 2b34e486bc): 'arg' variable no longer is available. If you fix some bugs, you should note the bug ID numbers in your commit message. -Bug ID should be prefixed by `#`. Example: - Fixed bug #14016 (pgsql notice handler double free crash bug.) + Fixed GH-14009: Fix prototype for trait method. -When you change the NEWS file for a bug fix, then please keep the bugs sorted in -decreasing order under the fixed version. +When you change the NEWS file for a bug fix, then please keep the bugs sorted +under the fixed version. ## Copyright and license headers @@ -453,4 +450,90 @@ New source code files should include the following header block: */ ``` +## NEWS + +The purpose of the NEWS file is to record all the changes that are relevant for +users and developers alike. These could be bug fixes, feature additions, syntax +additions, or deprecations. + +### Format + +Each PHP version has a section, starting with the format: + + {DD} {MMM} {YYY}, PHP {version} + +Such as: + + 06 Jun 2024, PHP 8.1.29 + +In each section, entries are ordered by their extension. Extensions are listed +alphabetically, with the exception of "Core", which MUST be listed first. Each +extension's section starts with: `- {name}:\n` + +For each extension, entries are indented by two spaces, followed by `. ` (a +period and a space). + +Entries MUST start with a capital and end with a period (`.`). The period goes +outside of the `{issue-description}`. + +Each entry SHOULD be followed by the name of the contributor, their php.net +account name, or their GitHub handle if they so choose. + +Entries MUST be wrapped at 80 characters. + +If an entry pertains a bug fix, they MUST be formatted as: + + Fixed bug GH-{number} ({issue-description}). ({contributor}) + +Bug fix entries SHOULD be clustered together, and ordered according to their +issue number. The `{issue-description}` SHOULD represent what the actual bug +fix is about, and not necessarily what the user reported. Edit the description +in the GitHub ticket to match. + +On the rare occasion where a bug from our deprecated bug system is fixed, the +entry MUST be formatted as: + + Fixed bug #{number} ({issue-description}). ({contributor}) + +An example: + +``` +31 Jul 2025, PHP 8.5.0alpha4 + +- Core: + . Added PHP_BUILD_PROVIDER constant. (timwolla) + . Fixed bug GH-16665 (\array and \callable should not be usable in + class_alias). (nielsdos) + . Fixed bug GH-19326 (Calling Generator::throw() on a running generator with + a non-Generator delegate crashes). (Arnaud) + +- OPcache: + . Make OPcache non-optional. (Arnaud, timwolla) + +- OpenSSL: + . Add $digest_algo parameter to openssl_public_encrypt() and + openssl_private_decrypt() functions. (Jakub Zelenka) + ``` + +### Branches + +Depending on what sort of fix it is, or where in the release cycle we are, +different NEWS files must be updated. + +*Security fixes*: In the lowest security-supported branch which received the +security fix, and in each newer branch, except for master unless alpha releases +have been tagged, and a release branch has not been created. + +*Bug fixes*: In the lowest supported branch, and in each newer branch, except +for master unless alpha releases have been tagged, and a release branch has not +been created. + +*Feature additions*: In master only. + +If for some reason a feature is introduced in a branch lower than master, +although this is strictly prohibited by other policies, then the entry must +also be in master. + +## Thanks + Thank you for contributing to PHP! diff --git a/EXTENSIONS b/EXTENSIONS index d15401f372384..01685748b5e09 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -196,7 +196,7 @@ MAINTENANCE: Maintained STATUS: Working ------------------------------------------------------------------------------- EXTENSION: lexbor -PRIMARY MAINTAINER: Niels Dossche (2023 - 2025) +PRIMARY MAINTAINER: Niels Dossche (2025 - 2025) Mate Kocsis (2025 - 2025) MAINTENANCE: Maintained STATUS: Working diff --git a/NEWS b/NEWS index 6ff942f86b2b7..5348bda28a005 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,416 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.5.0alpha1 +?? ??? ????, PHP 8.5.0RC1 + +- Core: + . Fixed bug GH-19765 (object_properties_load() bypasses readonly property + checks). (timwolla) + . The __sleep() and __wakeup() magic methods have been deprecated. (Girgias) + . Fixed hard_timeout with --enable-zend-max-execution-timers. (Appla) + +- Curl: + . Fix cloning of CURLOPT_POSTFIELDS when using the clone operator instead + of the curl_copy_handle() function to clone a CurlHandle. (timwolla) + +- Date: + . Fixed GH-17159: "P" format for ::createFromFormat swallows string literals. + (nielsdos) + +- Exif: + . Fix OSS-Fuzz #442954659 (zero-size box in HEIF file causes infinite loop). + (nielsdos) + . Fix OSS-Fuzz #442954659 (Crash in exif_scan_HEIF_header). (nielsdos) + . Various hardening fixes to HEIF parsing. (nielsdos) + +- Opcache: + . Fixed bug GH-19669 (assertion failure in zend_jit_trace_type_to_info_ex). + (Arnaud) + +- MBstring: + . Updated Unicode data tables to Unicode 17.0. (Yuya Hamada) + +- Standard: + . Passing strings which are not one byte long to ord() is now deprecated. + (Girgias) + +- URI: + . Fixed bug GH-19780 (InvalidUrlException should check $errors argument). + (nielsdos) + . Prevent modifying Uri\WhatWg\Url and Uri\Rfc3986\Uri objects by manually + calling __construct() or __unserialize(). (timwolla) + . Further clean up the internal API. (timwolla) + +- Windows: + . Fix GH-19722 (_get_osfhandle asserts in debug mode when given a socket). + (dktapps) + +11 Sep 2025, PHP 8.5.0beta3 + +- Core: + . Destructing non-array values (other than NULL) using [] or list() now + emits a warning. (Girgias) + . Fixed bug GH-19637 (Incorrect Closure scope for FCC in constant + expression). (timwolla) + . Fixed bug GH-19613 (Stale array iterator pointer). (ilutov) + . Fixed bug GH-19679 (zend_ssa_range_widening may fail to converge). (Arnaud) + . Using null as an array offset or when calling array_key_exists() is now + deprecated. (alexandre-daubois) + . Fixed bug GH-19681 (PHP_EXPAND_PATH broken with bash 5.3.0). (Remi) + . Marks the stack as non-executable on Haiku. (David Carlier) + . Deriving $_SERVER['argc'] and $_SERVER['argv'] from the query string is + now deprecated. (timwolla, nicolasgrekas) + +- CLI: + . Fixed bug GH-19461 (Improve error message on listening error with IPv6 + address). (alexandre-daubois) + +- Date: + . Fixed date_sunrise() and date_sunset() with partial-hour UTC offset. + (ilutov) + +- EXIF: + . Added support to retrieve Exif from HEIF file. (Benstone Zhang) + +- FPM: + . Fixed failed debug assertion when php_admin_value setting fails. (ilutov) + +- Filter: + . Fixed bug GH-16993 (filter_var_array with FILTER_VALIDATE_INT|FILTER_NULL_ON_FAILURE + should emit warning for invalid filter usage). (alexandre-daubois) + +- Intl: + . Added grapheme_strpos(), grapheme_stripos(), grapheme_strrpos(), + grapheme_strripos(), grapheme_strstr(), grapheme_stristr() and + grapheme_levenshtein() functions add $locale parameter (Yuya Hamada). + . Fixed bug GH-11952 (Fix locale strings canonicalization for IntlDateFormatter + and NumberFormatter). (alexandre-daubois) + +- ODBC: + . Removed driver-specific build flags and support. (Calvin Buckley) + +- Opcache: + . Fixed bug GH-19486 (Incorrect opline after deoptimization). (Arnaud) + . Fixed bug GH-19601 (Wrong JIT stack setup on aarch64/clang). (Arnaud) + . Fixed bug GH-19388 (Broken opcache.huge_code_pages). (Arnaud) + . Fixed bug GH-19657 (Build fails on non-glibc/musl/freebsd/macos/win + platforms). (Arnaud) + +- PCRE: + . Upgraded to pcre2lib from 10.45 to 10.46. (nielsdos) + +- PDO: + . Driver specific methods in the PDO class are now deprecated. (Arnaud) + +- PDO_SQLITE: + . Add PDO\Sqlite::ATTR_TRANSACTION_MODE connection attribute. + (Samuel Štancl) + +- Reflection: + . Fix GH-19691 (getModifierNames() not reporting asymmetric visibility). + (DanielEScherzer) + +- Session: + . Fix RC violation of session SID constant deprecation attribute. (ilutov) + +- Standard: + . Fix GH-19610 (Deprecation warnings in functions taking as argument). + (Girgias) + . Fixed bug GH-19577 (Avoid integer overflow when using a small offset + and PHP_INT_MAX with LimitIterator). (alexandre-daubois) + . Implement GH-19188: Add support for new INI mail.cr_lf_mode. + (alexandre-daubois) + +- Streams: + . Fixed bug GH-14506 (Closing a userspace stream inside a userspace handler + causes heap corruption). (nielsdos) + . Avoid double conversion to string in php_userstreamop_readdir(). (nielsdos) + +- URI: + . Added support for Uri\Rfc3986\Uri::with*() methods. (kocsismate) + . Fixed memory management of Uri\WhatWg\Url objects. (timwolla) + . Fixed memory management of the internal "parse_url" URI parser. + (timwolla) + . Fixed double-free when assigning to $errors fails when using + the Uri\WhatWg\Url parser. (timwolla) + . Reject out-of-range ports when using the Uri\Rfc3986\Uri parser. + (timwolla) + . Return null instead of 0 for Uri\Rfc3986\Uri::getPort() when the + URI contains an empty port. (timwolla) + . Fixed creation of the InvalidUrlException when not passing an + errors zval to the internal whatwg parser. (timwolla) + . Clean up naming of internal API. (timwolla) + +28 Aug 2025, PHP 8.5.0beta2 + +- Core: + . Fixed bug GH-18850 (Repeated inclusion of file with __halt_compiler() + triggers "Constant already defined" warning). (ilutov) + . Fixed bug GH-19476 (pipe operator fails to correctly handle returning + by reference). (alexandre-daubois) + . The report_memleaks INI directive has been deprecated. (alexandre-daubois) + . Constant redeclaration has been deprecated. (alexandre-daubois) + . Fixed OSS-Fuzz #439125710 (Pipe cannot be used in write context). + (nielsdos) + . Added support for configuring the URI parser for the FTP/FTPS as well as + the SSL/TLS stream wrappers as described in + https://wiki.php.net/rfc/url_parsing_api#plugability. (kocsismate) + . Fixed bug GH-19548 (Shared memory violation on property inheritance). + (alexandre-daubois) + . Fixed bug GH-19544 (GC treats ZEND_WEAKREF_TAG_MAP references as WeakMap + references). (Arnaud, timwolla) + . Introduced the TAILCALL VM, enabled by default when compiling with Clang>=19 + on x86_64 or aarch64. (Arnaud) + . Enacted the follow-up phase of the "Path to Saner Increment/Decrement + operators" RFC, meaning that incrementing non-numeric strings is now + deprecated. (Girgias). + . Various closure binding issues are now deprecated. (alexandre-daubois) + . Fixed bug GH-18373 (Don't substitute self/parent with anonymous class). + (ilutov) + . Prohibit pipe & arrow function combination that leads to confusing parse + trees. (ilutov) + . The disable_classes INI directive has been removed. (Girgias) + . The locally predefined variable $http_response_header is deprecated. + (Girgias) + +- Filter: + . Added support for configuring the URI parser for FILTER_VALIDATE_URL + as described in https://wiki.php.net/rfc/url_parsing_api#plugability. + (kocsismate) + +- ODBC: + . Remove ODBCVER and assume ODBC 3.5. (Calvin Buckley) + +- Opcache: + . Fixed bug GH-19493 (JIT variable not stored before YIELD). (Arnaud) + +- OpenSSL: + . Implement #81724 (openssl_cms_encrypt only allows specific ciphers). + (Jakub Zelenka) + +- PDO: + . Driver specific constants in the PDO class are now deprecated. (Arnaud) + +- Phar: + . Fixed memory leaks when verifying OpenSSL signature. (Girgias) + +- Session: + . Added support for partitioned cookies. (nielsdos) + +- SOAP: + . Added support for configuring the URI parser for SoapClient::_doRequest() + as described in https://wiki.php.net/rfc/url_parsing_api#plugability. + (kocsismate) + +- SPL: + . Deprecate ArrayObject and ArrayIterator with objects. (Girgias) + +- Standard: + . Fixed bug GH-16649 (UAF during array_splice). (alexandre-daubois) + . Passing integers outside the interval [0, 255] to chr() is now deprecated. + (Girgias) + . Added support for partitioned cookies. (nielsdos) + +- Tokenizer: + . Fixed bug GH-19507 (Corrupted result after recursive tokenization during + token_get_all()). (kubawerlos, nielsdos, Arnaud) + +- URI: + . Clean up naming of internal API (header names, symbol names). + (Máté Kocsis, timwolla) + +14 Aug 2025, PHP 8.5.0beta1 + +- Core: + . Non-canonical cast names (boolean), (integer), (double), and (binary) have + been deprecated. (Girgias) + . The $exclude_disabled parameter of the get_defined_functions() function has + been deprecated, as it no longer has any effect since PHP 8.0. (Girgias) + . Terminating case statements with a semicolon instead of a colon has + been deprecated. (theodorejb) + . The backtick operator as an alias for shell_exec() has been deprecated. + (timwolla) + . Returning null from __debugInfo() has been deprecated. (DanielEScherzer) + . Support #[\Override] on properties. (Jiří Pudil) + +- Curl: + . The curl_close() function has been deprecated. (DanielEScherzer) + . The curl_share_close() function has been deprecated. (DanielEScherzer) + +- Date: + . The DATE_RFC7231 and DateTimeInterface::RFC7231 constants have been + deprecated. (jorgsowa) + +- DOM: + . Fixed bug GH-18877 (\Dom\HTMLDocument querySelectorAll selecting only the + first when using ~ and :has). (nielsdos, lexborisov) + +- FileInfo + . The finfo_close() function has been deprecated. (timwolla) + . The $context parameter of the finfo_buffer() function has been deprecated + as it is ignored. (Girgias) + +- GD: + . The imagedestroy() function has been deprecated. (DanielEScherzer) + +- Intl: + . Intl's internal error mechanism has been modernized so that it + indicates more accurately which call site caused what error. + Moreover, some ext/date exceptions have been wrapped inside a + IntlException now. (Girgias) + . The intl.error_level INI setting has been deprecated. (Girgias) + +- MySQLi: + . The mysqli_execute() alias function has been deprecated. (timwolla) + +- OpenSSL: + . Fixed bug GH-19369 (8.5 | Regression in openssl_sign() - support for alias + algorithms appears to be broken). (Jakub Zelenka) + . The $key_length parameter for openssl_pkey_derive() has been deprecated. + (Girgias) + . Implement #80495 (Enable to set padding in openssl_(sign|verify). + (Jakub Zelenka) + . Implement #47728 (openssl_pkcs7_sign ignores new openssl flags). + (Jakub Zelenka) + +- PDO: + . The "uri:" DSN scheme has been deprecated due to security concerns with + DSNs coming from remote URIs. (timwolla) + +- Reflection: + . Fixed bug GH-17927 (Reflection: have some indication of property hooks in + `_property_string()`). (DanielEScherzer) + . The setAccessible() methods of various Reflection objects have been + deprecated, as those no longer have an effect. (timwolla) + . ReflectionClass::getConstant() for constants that do not exist has been + deprecated. (DanielEScherzer) + . ReflectionProperty::getDefaultValue() for properties without default values + has been deprecated. (DanielEScherzer) + +- SPL: + . Unregistering all autoloaders by passing the spl_autoload_call() function + as a callback argument to spl_autoload_unregister() has been deprecated. + Instead if this is needed, one should iterate over the return value of + spl_autoload_functions() and call spl_autoload_unregister() on each + value. (Girgias) + . The SplObjectStorage::contains(), SplObjectStorage::attach(), and + SplObjectStorage::detach() methods have been deprecated in favour of + SplObjectStorage::offsetExists(), SplObjectStorage::offsetSet(), and + SplObjectStorage::offsetUnset() respectively. (Girgias) + +- Standard: + . The socket_set_timeout() alias function has been deprecated. (timwolla) + . Passing null to to readdir(), rewinddir(), and closedir() to use the last + opened directory has been deprecated. (Girgias) + . Fixed bug GH-19153 (#[\Attribute] validation should error on + trait/interface/enum/abstract class). (DanielEScherzer) + +- XML: + . The xml_parser_free() function has been deprecated. (DanielEScherzer) + +31 Jul 2025, PHP 8.5.0alpha4 + +- Core: + . Add clone-with support to the clone() function. (timwolla, edorian) + . Fix support for non-userland stream notifiers. (timwolla) + . Added PHP_BUILD_PROVIDER constant. (timwolla) + . Fixed bug GH-19305 (Operands may be being released during comparison). + (Arnaud) + . Fixed bug GH-19306 (Generator can be resumed while fetching next value from + delegated Generator). (Arnaud) + . Fixed bug GH-19326 (Calling Generator::throw() on a running generator with + a non-Generator delegate crashes). (Arnaud) + +- Curl: + . Add support for CURLINFO_CONN_ID in curl_getinfo() (thecaliskan) + . Add support for CURLINFO_QUEUE_TIME_T in curl_getinfo() (thecaliskan) + . Add support for CURLOPT_SSL_SIGNATURE_ALGORITHMS. (Ayesh Karunaratne) + +- FPM: + . Make FPM access log limit configurable using log_limit. (Jakub Zelenka) + +- GD: + . Fix incorrect comparison with result of php_stream_can_cast(). (Girgias) + +- Intl: + . Fix return value on failure for resourcebundle count handler. (Girgias) + . Fixed bug GH-19307 (PGO builds of shared ext-intl are broken). (cmb) + +- OPcache: + . Disallow changing opcache.memory_consumption when SHM is already set up. + (timwolla) + . Fixed bug GH-15074 (Compiling opcache statically into ZTS PHP fails). + (Arnaud) + . Make OPcache non-optional (Arnaud, timwolla) + . Fixed bug GH-17422 (OPcache bypasses the user-defined error handler for + deprecations). (Arnaud, timwolla) + . Fixed bug GH-19301 (opcache build failure). (Remi) + +- OpenSSL: + . Add $digest_algo parameter to openssl_public_encrypt() and + openssl_private_decrypt() functions. (Jakub Zelenka) + +- POSIX: + . posix_kill and posix_setpgid throws a ValueError on invalid process_id. + (David Carlier) + . posix_setpgid throws a ValueError on invalid process_group_id, + posix_setrlimit throws a ValueError on invalid soft_limit and hard_limit + arguments. (David Carlier) + +- Reflection: + . Fixed bug GH-19187 (ReflectionNamedType::getName() prints nullable type when + retrieved from ReflectionProperty::getSettableType()). (ilutov) + +- Session: + . Fixed GH-19197: build broken with ZEND_STRL usage with memcpy + when implemented as macro. (David Carlier) + +- Soap: + . Fixed bug GH-19226 (Segfault when spawning new thread in soap extension). + (Florian Engelhardt) + +- Sockets: + . socket_set_option for multicast context throws a ValueError + when the socket family is not of AF_INET/AF_INET6 family. (David Carlier) + +- Standard: + . Add HEIF/HEIC support to getimagesize. (Benstone Zhang) + . Implement #71517 (Implement SVG support for getimagesize() and friends). + (nielsdos) + . Optimized PHP html_entity_decode function. (Artem Ukrainskiy) + . Minor optimization to array_chunk(). (nielsdos) + +- URI: + . Empty host handling is fixed. (Máté Kocsis) + . Error handling of Uri\WhatWg\Url::withHost() is fixed when the input + contains a port. Now, it triggers an exception; previously, the error + was silently swallowed. (Máté Kocsis) + . Support empty URIs with Uri\Rfc3986\Uri. (timwolla) + +17 Jul 2025, PHP 8.5.0alpha2 + +- Core: + . Fix OSS-Fuzz #427814452 (pipe compilation fails with assert). + (nielsdos, ilutov) + +- DOM: + . Make cloning DOM node lists, maps, and collections fail. (nielsdos) + . Added Dom\Element::getElementsByClassName(). (nielsdos) + +- PDO_ODBC + . Fetch larger block sizes and better handle SQL_NO_TOTAL when calling + SQLGetData. (Calvin Buckley, Saki Takamachi) + +- Standard: + . Optimized pack(). (nielsdos, divinity76) + . Fixed bug GH-19070 (setlocale($type, NULL) should not be deprecated). + (nielsdos) + +- URI: + . Return the singleton UrlValidationErrorType instances from Uri\WhatWg\Url + instead of creating new objects that are different from the singleton. + (timwolla) + +03 Jul 2025, PHP 8.5.0alpha1 - BCMath: . Simplify `bc_divide()` code. (SakiTakamachi) @@ -17,7 +427,7 @@ PHP NEWS - CURL: . Added CURLFOLLOW_ALL, CURLFOLLOW_OBEYCODE and CURLFOLLOW_FIRSTONLY - values for CURLOPT_FOLLOLOCATION curl_easy_setopt option. (David Carlier) + values for CURLOPT_FOLLOWLOCATION curl_easy_setopt option. (David Carlier) - COM: . Fixed property access of PHP objects wrapped in variant. (cmb) @@ -59,7 +469,9 @@ PHP NEWS . Added support for `final` with constructor property promotion. (DanielEScherzer) . Do not use RTLD_DEEPBIND if dlmopen is available. (Daniil Gentili) - . Make `clone() a function. (timwolla, edorian) + . Make `clone()` a function. (timwolla, edorian) + . Fixed bug GH-19081 (Wrong lineno in property error with constructor property + promotion). (ilutov) - Curl: . Added curl_multi_get_handles(). (timwolla) @@ -74,6 +486,7 @@ PHP NEWS - DOM: . Added Dom\Element::$outerHTML. (nielsdos) . Added Dom\Element::insertAdjacentHTML(). (nielsdos) + . Added $children property to ParentNode implementations. (nielsdos) - Enchant: . Added enchant_dict_remove_from_session(). (nielsdos) @@ -108,8 +521,8 @@ PHP NEWS . Added grapheme_levenshtein() function. (Yuya Hamada) . Added Locale::addLikelySubtags/Locale::minimizeSubtags to handle adding/removing likely subtags to a locale. (David Carlier) - . Added IntlListFormatter class to format a list of items with a locale - , operands types and units. (BogdanUngureanu) + . Added IntlListFormatter class to format a list of items with a locale, + operands types and units. (BogdanUngureanu) . Fixed bug GH-18566 ([intl] Weird numeric sort in Collator). (nielsdos) - LDAP: @@ -131,6 +544,11 @@ PHP NEWS . Log a warning when opcache lock file permissions could not be changed. (Taavi Eomäe) +- OpenSSL: + . Added openssl.libctx INI that allows to select the OpenSSL library context + type and convert various parts of the extension to use the custom libctx. + (Jakub Zelenka) + - Output: . Fixed calculation of aligned buffer size. (cmb) @@ -138,7 +556,7 @@ PHP NEWS . Extend pcntl_waitid with rusage parameter. (vrza) - PCRE: - . Upgraded to pre2lib from 10.44 to 10.45. (nielsdos) + . Upgraded to pcre2lib from 10.44 to 10.45. (nielsdos) . Remove PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK from pcre compile options. (mvorisek) @@ -184,8 +602,9 @@ PHP NEWS (DanielEScherzer) . Fixed bug GH-12856 (ReflectionClass::getStaticPropertyValue() returns UNDEF zval for uninitialized typed properties). (nielsdos) - . Fixed bug GH-15766 (ReflectionClass::toString() should have better output + . Fixed bug GH-15766 (ReflectionClass::__toString() should have better output for enums). (DanielEScherzer) + . Added ReflectionProperty::getMangledName() method. (alexandre-daubois) - Session: . session_start() throws a ValueError on option argument if not a hashmap @@ -246,7 +665,7 @@ PHP NEWS (David Carlier) - Sodium: - . Fix overall theorical overflows on zend_string buffer allocations. + . Fix overall theoretical overflows on zend_string buffer allocations. (David Carlier/nielsdos) - Sqlite: @@ -275,7 +694,7 @@ PHP NEWS (cmb) - Tests: - . Allow to shuffle tests even in non-parallell mode. (dhuang00) + . Allow to shuffle tests even in non-parallel mode. (dhuang00) - Tidy: . tidy::__construct/parseFile/parseString methods throw an exception if diff --git a/README.md b/README.md index c5376f67725cd..5b8ec6f0d7dc0 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ blog to the most popular websites in the world. PHP is distributed under the [PHP License v3.01](LICENSE). [![Push](https://github.com/php/php-src/actions/workflows/push.yml/badge.svg)](https://github.com/php/php-src/actions/workflows/push.yml) -[![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) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/php.svg)](https://issues.oss-fuzz.com/issues?q=project:php) ## Documentation @@ -42,28 +42,50 @@ a default build, you will additionally need libxml2 and libsqlite3. On Ubuntu, you can install these using: - sudo apt install -y pkg-config build-essential autoconf bison re2c \ - libxml2-dev libsqlite3-dev +```shell +sudo apt install -y pkg-config build-essential autoconf bison re2c libxml2-dev libsqlite3-dev +``` On Fedora, you can install these using: - sudo dnf install re2c bison autoconf make libtool ccache libxml2-devel sqlite-devel +```shell +sudo dnf install re2c bison autoconf make libtool ccache libxml2-devel sqlite-devel +``` + +On MacOS, you can install these using `brew`: + +```shell +brew install autoconf bison re2c libiconv libxml2 sqlite +``` + +or with `MacPorts`: + +```shell +sudo port install autoconf bison re2c libiconv libxml2 sqlite3 +``` Generate configure: - ./buildconf +```shell +./buildconf +``` Configure your build. `--enable-debug` is recommended for development, see `./configure --help` for a full list of options. - # For development - ./configure --enable-debug - # For production - ./configure +```shell +# For development +./configure --enable-debug +# For production +./configure +``` -Build PHP. To speed up the build, specify the maximum number of jobs using `-j`: +Build PHP. To speed up the build, specify the maximum number of jobs using the +`-j` argument: - make -j4 +```shell +make -j4 +``` The number of jobs should usually match the number of available cores, which can be determined using `nproc`. @@ -74,13 +96,21 @@ PHP ships with an extensive test suite, the command `make test` is used after successful compilation of the sources to run this test suite. It is possible to run tests using multiple cores by setting `-jN` in -`TEST_PHP_ARGS`: +`TEST_PHP_ARGS` or `TESTS`: - make TEST_PHP_ARGS=-j4 test +```shell +make TEST_PHP_ARGS=-j4 test +``` Shall run `make test` with a maximum of 4 concurrent jobs: Generally the maximum number of jobs should not exceed the number of cores available. +Use the `TEST_PHP_ARGS` or `TESTS` variable to test only specific directories: + +```shell +make TESTS=tests/lang/ test +``` + The [qa.php.net](https://qa.php.net) site provides more detailed info about testing and quality assurance. @@ -88,9 +118,11 @@ testing and quality assurance. After a successful build (and test), PHP may be installed with: - make install +```shell +make install +``` -Depending on your permissions and prefix, `make install` may need super user +Depending on your permissions and prefix, `make install` may need superuser permissions. ## PHP extensions diff --git a/UPGRADING b/UPGRADING index 4d968ef4daf80..09675d91ee0ce 100644 --- a/UPGRADING +++ b/UPGRADING @@ -19,12 +19,6 @@ PHP 8.5 UPGRADE NOTES 1. Backward Incompatible Changes ======================================== -- BZ2: - . bzcompress() now throws a ValueError when $block_size is not between - 1 and 9. - . bzcompress() now throws a ValueError when $work_factor is not between - 0 and 250. - - Core: . It is no longer possible to use "array" and "callable" as class alias names in class_alias(). @@ -44,6 +38,35 @@ PHP 8.5 UPGRADE NOTES . Traits are now bound before the parent class. This is a subtle behavioral change, but should more closely match user expectations, demonstrated by GH-15753 and GH-16198. + . Errors emitted during compilation and class linking are now always delayed + and handled after compilation or class linking. Fatal errors emitted during + compilation or class linking cause any delayed errors to be handled + immediately, without calling user-defined error handlers. + . Exceptions thrown by user-defined error handlers when handling class linking + errors are not promoted to fatal errors anymore and do not prevent linking. + . Applying #[\Attribute] to an abstract class, enum, interface, or trait triggers + an error during compilation. Previously, the attribute could be added, but when + ReflectionAttribute::newInstance() was called an error would be thrown. + The error can be delayed from compilation to runtime using the new + #[\DelayedTargetValidation] attribute. + . The disable_classes INI setting has been removed as it causes various + engine assumptions to be broken. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#remove_disable_classes_ini_setting + . Destructing non-array values (other than NULL) using [] or list() now + emits a warning. + RFC: https://wiki.php.net/rfc/warnings-php-8-5#destructuring_non-array_values + +- BZ2: + . bzcompress() now throws a ValueError when $block_size is not between + 1 and 9. + . bzcompress() now throws a ValueError when $work_factor is not between + 0 and 250. + +- DOM: + . Cloning a DOMNamedNodeMap, DOMNodeList, Dom\NamedNodeMap, Dom\NodeList, + Dom\HTMLCollection, and Dom\DtdNamedNodeMap now fails. + This never actually resulted in a working object, + so the impact should actually be zero. - FileInfo: . finfo_file() and finfo::file() now throws a ValueError instead of a @@ -61,10 +84,30 @@ PHP 8.5 UPGRADE NOTES . ldap_get_option() and ldap_set_option() now throw a ValueError when passing an invalid option. +- MBstring: + . Unicode data tables have been updated to Unicode 17.0 + - MySQLi: . Calling the mysqli constructor on an already-constructed object is now no longer possible and throws an Error. +- ODBC: + . ODBC now assumes that at least ODBC 3.5 functionality is available. The + ODBCVER definition and build system flags to control it have been removed. + . ODBC no longer has build flags to build against specific drivers (except + for DB2) and removes special cases for those drivers. It is strongly + recommended to use a driver manager like iODBC or unixODBC on non-Windows. + +- Opcache: + . The Opcache extension is now always built into the PHP binary and is always + loaded. The INI directives opcache.enable and opcache.enable_cli are still + honored. + The --enable-opcache/--disable-opcache configure flags have been removed, + and the build does not produce opcache.so or php_opcache.dll objects + anymore. + Using zend_extension=opcache.so or zend_extension=php_opcache.dll INI + directives will emit a warning. + - PCNTL: . pcntl_exec() now throws ValueErrors when entries of the $args parameter contain null bytes. @@ -153,6 +196,13 @@ PHP 8.5 UPGRADE NOTES RFC: https://wiki.php.net/rfc/pipe-operator-v3 . Constructor property promotion can now be used for final properties. RFC: https://wiki.php.net/rfc/final_promotion + . #[\Override] can now be applied to properties. + RFC: https://wiki.php.net/rfc/override_properties + . The #[\DelayedTargetValidation] attribute can be used to suppress + compile-time errors from core (or extension) attributes that are used on + invalid targets. These errors are instead reported at runtime if and when + ReflectionAttribute::newInstance() is called. + RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute - Curl: . Added support for share handles that are persisted across multiple PHP @@ -182,12 +232,26 @@ PHP 8.5 UPGRADE NOTES first redirect thus if there is any follow up redirect, it won't go any further. CURLFOLLOW_ALL is equivalent to setting CURLOPT_FOLLOWLOCATION to true. + . Added support for CURLINFO_CONN_ID (libcurl >= 8.2.0) to the curl_getinfo() + function. This constant allows retrieving the unique ID of the connection + used by a cURL transfer. It is primarily useful when connection reuse or + connection pooling logic is needed in PHP-level applications. When + curl_getinfo() returns an array, this value is available as the "conn_id" key. + . Added support for CURLINFO_QUEUE_TIME_T (libcurl >= 8.6.0) to the curl_getinfo() + function. This constant allows retrieving the time (in microseconds) that the + request spent in libcurl’s connection queue before it was sent. + This value can also be retrieved by passing CURLINFO_QUEUE_TIME_T to the + curl_getinfo() $option parameter. + . Added support for CURLOPT_SSL_SIGNATURE_ALGORITHMS to specify the signature + algorithms to use for TLS. - DOM: . Added Dom\Element::$outerHTML. + . Added $children property to Dom\ParentNode implementations. - EXIF: . Add OffsetTime* Exif tags. + . Added support for HEIF/HEIC. - Intl: . Added class constants NumberFormatter::CURRENCY_ISO, @@ -208,6 +272,16 @@ PHP 8.5 UPGRADE NOTES . Added class constants Pdo_Sqlite::ATTR_EXPLAIN_STATEMENT, Pdo_Sqlite::EXPLAIN_MODE_PREPARED, Pdo_Sqlite::EXPLAIN_MODE_EXPLAIN, Pdo_Sqlite::EXPLAIN_MODE_EXPLAIN_QUERY_PLAN. + . Added PDO\Sqlite::ATTR_TRANSACTION_MODE connection attribute with + possible values PDO\Sqlite::TRANSACTION_MODE_DEFERRED, + PDO\Sqlite::TRANSACTION_MODE_IMMEDIATE, + and PDO\Sqlite::TRANSACTION_MODE_EXCLUSIVE, allowing to configure + the transaction mode to use when calling beginTransaction(). + +- Session: + . session_set_cookie_params(), session_get_cookie_params(), and session_start() + now support partitioned cookies via the "partitioned" key. + RFC: https://wiki.php.net/rfc/CHIPS - SOAP: . Enumeration cases are now dumped in __getTypes(). @@ -227,6 +301,16 @@ PHP 8.5 UPGRADE NOTES process was terminated unexpectedly. In such cases, a warning is emitted and the function returns false. Previously, these errors were silently ignored. This change affects only the sendmail transport. + . getimagesize() now supports HEIF/HEIC images. + . getimagesize() now supports SVG images when ext-libxml is also loaded. + Similarly, image_type_to_extension() and image_type_to_mime_type() + now also handle IMAGETYPE_SVG. + . The array returned by getimagesize() now has two additional entries: + "width_unit" and "height_unit" to indicate in which units the dimensions + are expressed. These units are px by default. They are not necessarily + the same (just to give one example: one may be cm and the other may be px). + . setcookie() and setrawcookie() now support the "partitioned" key. + RFC: https://wiki.php.net/rfc/CHIPS - XSL: . The $namespace argument of XSLTProcessor::getParameter(), @@ -253,16 +337,236 @@ PHP 8.5 UPGRADE NOTES - FPM: . FPM with httpd ProxyPass decodes the full script path. Added fastcgi.script_path_encoded INI setting to prevent this new behavior. + . FPM access log limit now respects log_limit value. ======================================== 4. Deprecated Functionality ======================================== +- Core: + . Returning a non-string from a user output handler is deprecated. The + deprecation warning will bypass the handler with the bad return to ensure + it is visible; if there are nested output handlers the next one will still + be used. + RFC: https://wiki.php.net/rfc/deprecations_php_8_4 + . Trying to produce output (e.g. with `echo`) within a user output handler + is deprecated. The deprecation warning will bypass the handler producing the + output to ensure it is visible; if there are nested output handlers the next + one will still be used. If a user output handler returns a non-string and + produces output, the warning about producing an output is emitted first. + RFC: https://wiki.php.net/rfc/deprecations_php_8_4 + . Non-canonical cast names (boolean), (integer), (double), and (binary) have + been deprecated, use (bool), (int), (float), and (string) respectively. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_non-standard_cast_names + . The $exclude_disabled parameter of the get_defined_functions() function has + been deprecated, as it no longer has any effect since PHP 8.0. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_exclude_disabled_parameter_of_get_defined_functions + . Terminating case statements with a semicolon instead of a colon has + been deprecated. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_semicolon_after_case_in_switch_statement + . The backtick operator as an alias for shell_exec() has been deprecated. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_backticks_as_an_alias_for_shell_exec + . Returning null from __debugInfo() has been deprecated. + Return an empty array instead. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_debuginfo_returning_null + . The report_memleaks INI directive has been deprecated. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_report_memleaks_ini_directive + . Constant redeclaration has been deprecated. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_constant_redeclaration + . Enacted the follow-up phase of the "Path to Saner Increment/Decrement + operators" RFC, meaning that incrementing non-numeric strings is now + deprecated. Instead the str_increment() function should be used. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#enact_follow-up_phase_of_the_path_to_saner_incrementdecrement_operators_rfc + . The following closure binding issues, which already emit an E_WARNING, are + now deprecated: + - Binding an instance to a static closure + - Binding methods to objects that are not instances of the class + (or subclass) that the method is defined + - Unbinding $this from a method + - Unbinding $this from a closure that uses `$this` + - Binding a closure to the scope of an internal class + - Rebinding the scope of a closure created from a function or method + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_closure_binding_issues + . Using null as an array offset or when calling array_key_exists() is now + deprecated. Instead an empty string should be used. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_using_values_null_as_an_array_offset_and_when_calling_array_key_exists + . Deriving $_SERVER['argc'] and $_SERVER['argv'] from the query string for non-CLI + SAPIs has been deprecated. Configure register_argc_argv=0 and switch to either + $_GET or $_SERVER['QUERY_STRING'] to access the information, after verifying + that the usage is safe. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_register_argc_argv_ini_directive + . The __sleep() and __wakeup() magic methods have been deprecated. The + __serialize() and __unserialize() magic methods should be used instead, + or at the same time if compatibility with PHP 7 is required. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_sleep_and_wakeup_magic_methods + +- Curl: + . The curl_close() function has been deprecated, as CurlHandle objects are + freed automatically. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_curl_close + . The curl_share_close() function has been deprecated, as CurlShareHandle + objects are freed automatically. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_curl_share_close + +- Date: + . The DATE_RFC7231 and DateTimeInterface::RFC7231 constants have been + deprecated. This is because the associated timezone is ignored and always + uses GMT. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_date_rfc7231_and_datetimeinterfacerfc7231 + +- FileInfo: + . The finfo_close() function has been deprecated. + As finfo objects are freed automatically. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_finfo_close + . The $context parameter of the finfo_buffer() function has been deprecated + as it is ignored. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_context_parameter_for_finfo_buffer + +- GD: + . The imagedestroy() function has been deprecated, as GdImage objects are + freed automatically. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_imagedestroy + - Hash: . The MHASH_* constants have been deprecated. These have been overlooked when the mhash*() function family has been deprecated per https://wiki.php.net/rfc/deprecations_php_8_1#mhash_function_family +- Intl: + . The intl.error_level INI setting has been deprecated. + Errors should either be checked manually or exceptions should be enabled + by using the intl.use_exceptions INI setting. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_intlerror_level_ini_setting + +- MySQLi: + . The mysqli_execute() alias function has been deprecated. + Use mysqli_stmt_execute() instead. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#formally_deprecate_mysqli_execute + +- OpenSSL: + . The $key_length parameter for openssl_pkey_derive() has been deprecated. + This is because it is either ignored, or truncates the key, which can be + a vulnerability. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_key_length_parameter_of_openssl_pkey_derive + +- PDO: + . The "uri:" DSN scheme has been deprecated due to security concerns with + DSNs coming from remote URIs. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_pdo_s_urischeme + . Driver specific constants in the PDO class have been deprecated. + List of affected constants and their replacement: + PDO::DBLIB_ATTR_CONNECTION_TIMEOUT => Pdo\Dblib::ATTR_CONNECTION_TIMEOUT + PDO::DBLIB_ATTR_QUERY_TIMEOUT => Pdo\Dblib::ATTR_QUERY_TIMEOUT + PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER => Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER + PDO::DBLIB_ATTR_VERSION => Pdo\Dblib::ATTR_VERSION + PDO::DBLIB_ATTR_TDS_VERSION => Pdo\Dblib::ATTR_TDS_VERSION + PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS => Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS + PDO::DBLIB_ATTR_DATETIME_CONVERT => Pdo\Dblib::ATTR_DATETIME_CONVERT + PDO::FB_ATTR_DATE_FORMAT => Pdo\Firebird::ATTR_DATE_FORMAT + PDO::FB_ATTR_TIME_FORMAT => Pdo\Firebird::ATTR_TIME_FORMAT + PDO::FB_ATTR_TIMESTAMP_FORMAT => Pdo\Firebird::ATTR_TIMESTAMP_FORMAT + PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => Pdo\Mysql::ATTR_USE_BUFFERED_QUERY + PDO::MYSQL_ATTR_LOCAL_INFILE => Pdo\Mysql::ATTR_LOCAL_INFILE + PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY => Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY + PDO::MYSQL_ATTR_INIT_COMMAND => Pdo\Mysql::ATTR_INIT_COMMAND + PDO::MYSQL_ATTR_MAX_BUFFER_SIZE => Pdo\Mysql::ATTR_MAX_BUFFER_SIZE + PDO::MYSQL_ATTR_READ_DEFAULT_FILE => Pdo\Mysql::ATTR_READ_DEFAULT_FILE + PDO::MYSQL_ATTR_READ_DEFAULT_GROUP => Pdo\Mysql::ATTR_READ_DEFAULT_GROUP + PDO::MYSQL_ATTR_COMPRESS => Pdo\Mysql::ATTR_COMPRESS + PDO::MYSQL_ATTR_DIRECT_QUERY => Pdo\Mysql::ATTR_DIRECT_QUERY + PDO::MYSQL_ATTR_FOUND_ROWS => Pdo\Mysql::ATTR_FOUND_ROWS + PDO::MYSQL_ATTR_IGNORE_SPACE => Pdo\Mysql::ATTR_IGNORE_SPACE + PDO::MYSQL_ATTR_SSL_KEY => Pdo\Mysql::ATTR_SSL_KEY + PDO::MYSQL_ATTR_SSL_CERT => Pdo\Mysql::ATTR_SSL_CERT + PDO::MYSQL_ATTR_SSL_CA => Pdo\Mysql::ATTR_SSL_CA + PDO::MYSQL_ATTR_SSL_CAPATH => Pdo\Mysql::ATTR_SSL_CAPATH + PDO::MYSQL_ATTR_SSL_CIPHER => Pdo\Mysql::ATTR_SSL_CIPHER + PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT + PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY => Pdo\Mysql::ATTR_SERVER_PUBLIC_KEY + PDO::MYSQL_ATTR_MULTI_STATEMENTS => Pdo\Mysql::ATTR_MULTI_STATEMENTS + PDO::ODBC_ATTR_USE_CURSOR_LIBRARY => Pdo\Odbc::ATTR_USE_CURSOR_LIBRARY + PDO::ODBC_ATTR_ASSUME_UTF8 => Pdo\Odbc::ATTR_ASSUME_UTF8 + PDO::ODBC_SQL_USE_IF_NEEDED => Pdo\Odbc::SQL_USE_IF_NEEDED + PDO::ODBC_SQL_USE_DRIVER => Pdo\Odbc::SQL_USE_DRIVER + PDO::ODBC_SQL_USE_ODBC => Pdo\Odbc::SQL_USE_ODBC + PDO::PGSQL_ATTR_DISABLE_PREPARES => Pdo\Pgsql::ATTR_DISABLE_PREPARES + PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES => Pdo\Sqlite::ATTR_EXTENDED_RESULT_CODES + PDO::SQLITE_ATTR_OPEN_FLAGS => Pdo\Sqlite::OPEN_FLAGS + PDO::SQLITE_ATTR_READONLY_STATEMENT => Pdo\Sqlite::ATTR_READONLY_STATEMENT + PDO::SQLITE_DETERMINISTIC => Pdo\Sqlite::DETERMINISTIC + PDO::SQLITE_OPEN_READONLY => Pdo\Sqlite::OPEN_READONLY + PDO::SQLITE_OPEN_READWRITE => Pdo\Sqlite::OPEN_READWRITE + PDO::SQLITE_OPEN_CREATE => Pdo\Sqlite::OPEN_CREATE + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_driver_specific_pdo_constants_and_methods + . Driver specific methods in the PDO class have been deprecated. + List of affected methods and their replacement: + PDO::pgsqlCopyFromArray() => Pdo\Pgsql::copyFromArray() + PDO::pgsqlCopyFromFile() => Pdo\Pgsql::copyFromFile() + PDO::pgsqlCopyToArray() => Pdo\Pgsql::copyToArray() + PDO::pgsqlCopyToFile() => Pdo\Pgsql::copyToFile() + PDO::pgsqlGetNotify() => Pdo\Pgsql::getNotify() + PDO::pgsqlGetPid() => Pdo\Pgsql::getPid() + PDO::pgsqlLOBCreate() => Pdo\Pgsql::lobCreate() + PDO::pgsqlLOBOpen() => Pdo\Pgsql::lobOpen() + PDO::pgsqlLOBUnlink() => Pdo\Pgsql::lobUnlink() + PDO::sqliteCreateAggregate() => Pdo\Sqlite::createAggregate() + PDO::sqliteCreateCollation() => Pdo\Sqlite::createCollation() + PDO::sqliteCreateFunction() => Pdo\Sqlite::createFunction() + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_driver_specific_pdo_constants_and_methods + +- PDO_PGSQL: Constants related to transaction states have been deprecated: + PDO::PGSQL_TRANSACTION_IDLE, PDO::PGSQL_TRANSACTION_ACTIVE, PDO::PGSQL_TRANSACTION_INTRANS, + PDO::PGSQL_TRANSACTION_INERROR, PDO::PGSQL_TRANSACTION_UNKNOWN. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#extpdo_deprecations + +- Reflection: + . The setAccessible() methods of various Reflection objects have been + deprecated, as those no longer have an effect. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_reflectionsetaccessible + . Calling ReflectionClass::getConstant() for constants that do not exist has + been deprecated. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_reflectionclassgetconstant_for_missing_constants + . Calling ReflectionProperty::getDefaultValue() for properties without default + values has been deprecated. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_reflectionpropertygetdefaultvalue_for_properties_without_default_values + +- SPL: + . Unregistering all autoloaders by passing the spl_autoload_call() function + as a callback argument to spl_autoload_unregister() has been deprecated. + Instead if this is needed, one should iterate over the return value of + spl_autoload_functions() and call spl_autoload_unregister() on each value. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_spl_autoload_call_to_spl_autoload_unregister + . The SplObjectStorage::contains(), SplObjectStorage::attach(), and + SplObjectStorage::detach() methods have been deprecated in favour of + SplObjectStorage::offsetExists(), SplObjectStorage::offsetSet(), and + SplObjectStorage::offsetUnset() respectively. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_splobjectstoragecontains_splobjectstorageattach_and_splobjectstoragedetach + . Using ArrayObject and ArrayIterator with objects has been deprecated. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_arrayobject_and_arrayiterator_with_objects + +- Standard: + . The socket_set_timeout() alias function has been deprecated. + Use stream_set_timeout() instead. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#formally_deprecate_socket_set_timeout + . Passing null to to readdir(), rewinddir(), and closedir() to use the last + opened directory has been deprecated. Provide the last opened directory + explicitly instead. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_null_to_readdir_rewinddir_and_closedir + . Passing integers outside the interval [0, 255] to chr() is now deprecated. + This is because a byte can only hold a value within this interval. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_integers_outside_the_interval_0_255_to_chr + . Passing a string which is not a single byte to ord() is now deprecated, + this is indicative of a bug. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_string_which_are_not_one_byte_long_to_ord + . Relying locally predefined variable $http_response_header is deprecated. + Instead one should call the http_get_last_response_headers() function. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_http_response_header_predefined_variable + +- XML: + . The xml_parser_free() function has been deprecated, as XMLParser objects + are freed automatically. + RFC: https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_xml_parser_free + ======================================== 5. Changed Functions ======================================== @@ -279,6 +583,10 @@ PHP 8.5 UPGRADE NOTES TransLiterator::getErrorCode(), and TransLiterator::getErrorMessage() have dropped the false from the return type union. Returning false was actually never possible. + . grapheme_strpos(), grapheme_stripos(), grapheme_strrpos(), + grapheme_strripos(), grapheme_strstr(), grapheme_stristr() and + grapheme_levenshtein() functions add $locale parameter. + RFC: https://wiki.php.net/rfc/grapheme_add_locale_for_case_insensitive - LDAP: . ldap_get_option() now accepts a NULL connection, as ldap_set_option(), @@ -287,6 +595,15 @@ PHP 8.5 UPGRADE NOTES - libxml: . libxml_set_external_entity_loader() now has a formal return type of true. +- OpenSSL: + . openssl_public_encrypt() and openssl_private_decrypt() have new parameter + $digest_algo that allows specifying hash digest algorithm for OEAP padding. + . openssl_sign() and openssl_verify() have new parameter $padding to allow + using more secure RSA PSS padding. + . openssl_cms_encrypt() $cipher_algo parameter can be a string with the + cipher name. That allows to use more algorithms including AES GCM cipher + algorithms for auth enveloped data. + - PCNTL: . pcntl_exec() now has a formal return type of false. . pcntl_waitid() takes an additional resource_usage argument to @@ -319,16 +636,33 @@ PHP 8.5 UPGRADE NOTES an invalid file descriptor. . posix_fpathconf checks invalid file descriptors and sets last_error to EBADF and raises an E_WARNING message. + . posix_kill throws a ValueError when the process_id argument is lower + or greater than what supports the platform (signed integer or long + range), posix_setpgid throws a ValueError when the process_id or + the process_group_id is lower than zero or greater than + what supports the platform. + . posix_setrlimit throws a ValueError when the hard_limit of soft_limit + argument are lower than -1 or if soft_limit is greater than hard_limit. - Reflection: - . The output of ReflectionClass::toString() for enums has changed to + . The output of ReflectionClass::__toString() for enums has changed to better indicate that the class is an enum, and that the enum cases are enum cases rather than normal class constants. + . The output of ReflectionProperty::__toString() for properties with + hooks has changed to indicate what hooks the property has, whether those + hooks are final, and whether the property is virtual. This also affects + the output of ReflectionClass::__toString() when a class contains hooked + properties. + . ReflectionAttribute::newInstance() can now throw errors for internal + attributes if the attribute was applied on an invalid target and the + error was delayed from compile-time to runtime via the + #[\DelayedTargetValidation] attribute. + RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute - Session: . session_start is stricter in regard to the option argument. It throws a ValueError if the whole is not a hashmap or - a TypeError if read_on_close value is not a valid type + a TypeError if read_and_close value is not a valid type compatible with int. - SNMP: @@ -341,7 +675,7 @@ PHP 8.5 UPGRADE NOTES - Sockets: . socket_create_listen, socket_bind and socket_sendto throw a ValueError if the port is lower than 0 or greater than 65535, - also if any of the hints array entry is indexes numerically. + and also if any of the hints array entries are indexed numerically. . socket_addrinfo_lookup throws a TypeError if any of the hints values cannot be cast to int and can throw a ValueError if any of these values overflow. @@ -351,6 +685,8 @@ PHP 8.5 UPGRADE NOTES . socket_create/socket_bind can create AF_PACKET family sockets. . socket_getsockname gets the interface index and its string representation with AF_PACKET socket. + . socket_set_option with multicast context throws a ValueError + when the created socket is not of AF_INET/AF_INET6 family. - Tidy: . tidy::__construct/parseFile/parseString now throws a ValueError @@ -376,8 +712,10 @@ PHP 8.5 UPGRADE NOTES . get_exception_handler() allows retrieving the current user-defined exception handler function. RFC: https://wiki.php.net/rfc/get-error-exception-handler - . The clone language construct is now a function. + . The clone language construct is now a function and supports reassigning + (readonly) properties during cloning via the new $withProperties parameter. RFC: https://wiki.php.net/rfc/clone_with_v2 + . Added Closure::getCurrent() to receive currently executing closure. - Curl: . curl_multi_get_handles() allows retrieving all CurlHandles current @@ -388,6 +726,7 @@ PHP 8.5 UPGRADE NOTES RFC: https://wiki.php.net/rfc/curl_share_persistence_improvement - DOM: + . Added Dom\Element::getElementsByClassName(). . Added Dom\Element::insertAdjacentHTML(). - Enchant: @@ -402,6 +741,9 @@ PHP 8.5 UPGRADE NOTES . Added grapheme_levenshtein() function. RFC: https://wiki.php.net/rfc/grapheme_levenshtein +- Opcache: + . Added opcache_is_script_cached_in_file_cache(). + - Pdo\Sqlite: . Added support for Pdo\Sqlite::setAuthorizer(), which is the equivalent of SQLite3::setAuthorizer(). The only interface difference is that the @@ -419,6 +761,7 @@ PHP 8.5 UPGRADE NOTES ReflectionConstant::getExtensionName() were introduced. . ReflectionConstant::getAttributes() was introduced. RFC: https://wiki.php.net/rfc/attributes-on-constants + . ReflectionProperty::getMangledName() was introduced. - Sqlite: . Sqlite3Stmt::busy to check if a statement had been fetched @@ -432,11 +775,24 @@ PHP 8.5 UPGRADE NOTES 7. New Classes and Interfaces ======================================== +- Core: + . NoDiscard attribute was added. + RFC: https://wiki.php.net/rfc/marking_return_value_as_important + . DelayedTargetValidation attribute was added. + RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute + - Curl: . CurlSharePersistentHandle representing a share handle that is persisted across multiple PHP requests. RFC: https://wiki.php.net/rfc/curl_share_persistence_improvement +- URI: + . Uri\UriException, Uri\InvalidUriException, Uri\UriComparisonMode, + Uri\Rfc3986\Uri, Uri\WhatWg\InvalidUrlException, + Uri\WhatWg\UrlValidationErrorType, Uri\WhatWg\UrlValidationError, + and Uri\WhatWg\Url are added. + RFC: https://wiki.php.net/rfc/url_parsing_api + ======================================== 8. Removed Extensions and SAPIs ======================================== @@ -451,17 +807,33 @@ PHP 8.5 UPGRADE NOTES CURLFOLLOW_FIRSTONLY. - Fileinfo: - . Upgraded to file 5.46. + . Upgraded file from 5.45 to 5.46. . The return type of finfo_close() has been changed to true, rather than bool. +- Intl: + . Intl's internal error mechanism has been modernized so that it + indicates more accurately which call site caused what error. + Moreover, some ext/date exceptions have been wrapped inside a + IntlException now. + - Lexbor: . An always enabled lexbor extension is added. It contains the lexbor library that was separated from ext/dom for being reused among other extensions. The new extension is not directly exposed to userland. +- Opcache: + . The Opcache extension is now always built into the PHP binary and is always + loaded. The INI directives opcache.enable and opcache.enable_cli are still + honored. + +- URI: + . An always enabled uri extension is added that can be used for handling + URIs and URLs according to RFC 3986 and WHATWG URL. + RFC: https://wiki.php.net/rfc/url_parsing_api + - PCRE: - . Upgraded to pcre2lib from 10.44 to 10.45. + . Upgraded pcre2lib from 10.44 to 10.46. - PDO_Sqlite: . Increased minimum release version support from 3.7.7 to 3.7.17. @@ -477,11 +849,14 @@ PHP 8.5 UPGRADE NOTES - Core: . PHP_BUILD_DATE. + . PHP_BUILD_PROVIDER. - Curl: . CURLINFO_USED_PROXY. . CURLINFO_HTTPAUTH_USED. . CURLINFO_PROXYAUTH_USED. + . CURLINFO_CONN_ID. + . CURLINFO_QUEUE_TIME_T. . CURLOPT_INFILESIZE_LARGE. . CURLFOLLOW_ALL. . CURLFOLLOW_OBEYCODE. @@ -491,6 +866,13 @@ PHP 8.5 UPGRADE NOTES . DECIMAL_COMPACT_SHORT. . DECIMAL_COMPACT_LONG. +- OpenSSL: + . OPENSSL_PKCS1_PSS_PADDING + . PKCS7_NOSMIMECAP + . PKCS7_CRLFEOL + . PKCS7_NOCRL + . PKCS7_NO_DUAL_CONTENT + - POSIX: . POSIX_SC_OPEN_MAX. @@ -514,6 +896,9 @@ PHP 8.5 UPGRADE NOTES . T_VOID_CAST. . T_PIPE. +- Standard: + . IMAGETYPE_SVG when libxml is loaded. + ======================================== 11. Changes to INI File Handling ======================================== @@ -522,6 +907,11 @@ PHP 8.5 UPGRADE NOTES . Added fatal_error_backtraces to control whether fatal errors should include a backtrace. RFC: https://wiki.php.net/rfc/error_backtraces_v2 + . Added startup-only max_memory_limit INI setting to control the maximum + memory_limit that may be configured at startup or runtime. Exceeding this + value emits a warning, unless set to -1, and sets memory_limit to the + current max_memory_limit instead. + ML discussion: https://externals.io/message/127108 - Opcache: . Added opcache.file_cache_read_only to support a read-only @@ -536,6 +926,14 @@ PHP 8.5 UPGRADE NOTES . The default value of opcache.jit_hot_loop is now 61 (a prime) to prevent it from being a multiple of loop iteration counts. It is recommended that this parameter is set to a prime number. + . Changing opcache.memory_consumption when OPcache SHM is already set up + will now correctly report a failure instead of silently doing nothing and + showing misleading values in PHPInfo. + +- OpenSSL: + . Added openssl.libctx to select the OpenSSL library context type. Either + custom libctx for each thread can be used or a single global (default) + libctx is used. ======================================== 12. Windows Support @@ -585,6 +983,13 @@ PHP 8.5 UPGRADE NOTES . The `-z` or `--zend-extension` option has been removed as it was non-functional. Use `-d zend_extension=` instead. +- PDO_ODBC + . The fetch behaviour for larger columns has been changed. Rather than + fetching 256 byte blocks, PDO_ODBC will try to fetch a larger block size; + currently, this is the page size minus string overhead. Drivers that + return SQL_NO_TOTAL in SQLGetData are also better handled as well. + This should improve compatibility and performance. See GH-10809, GH-10733. + ======================================== 14. Performance Improvements ======================================== @@ -596,6 +1001,11 @@ PHP 8.5 UPGRADE NOTES . Creating exception objects is now much faster. . The parts of the code that used SSE2 have been adapted to use SIMD with ARM NEON as well. + . Introduced the TAILCALL VM, enabled by default when compiling with Clang>=19 + on x86_64 or aarch64. The TAILCALL VM is as fast as the HYBRID VM used when + compiling with GCC. This makes PHP binaries built with Clang>=19 as fast as + binaries built with GCC. The performance of the CALL VM, used with other + compilers, has also improved considerably. - Intl: . Now avoids creating extra string copies when converting strings @@ -605,6 +1015,10 @@ PHP 8.5 UPGRADE NOTES . The parts of the code that used SSE2 have been adapted to use SIMD with ARM NEON as well. +- Opcache: + . Improved performance of fetching TLS variables in JIT'ed code in non-Glibc + builds. + - ReflectionProperty: . Improved performance of the following methods: getValue(), getRawValue(), isInitialized(), setValue(), setRawValue(). @@ -618,6 +1032,8 @@ PHP 8.5 UPGRADE NOTES . Improved performance of urlencode() and rawurlencode(). . Improved unpack() performance with nameless repetitions by avoiding creating temporary strings and reparsing them. + . Improved pack() performance. + . Minor improvements in array_chunk() performance. - XMLReader: . Improved property access performance. diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index acc9612b72e30..66f7fea5a724e 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -14,7 +14,6 @@ PHP 8.5 INTERNALS UPGRADE NOTES 1. Internal API changes ======================== -- Core . PG(arg_separator).input and PG(arg_separator).output are now `zend_string*` instead of `char*`. . DL_LOAD now doesn't use RTLD_DEEPBIND deepbind anymore on platforms @@ -23,8 +22,17 @@ PHP 8.5 INTERNALS UPGRADE NOTES the user side when requiring libphp.so, by using dlmopen with LM_ID_NEWLM instead of dlopen. RTLD_DEEPBIND is still enabled when the Apache SAPI is in use. - -- Zend + . The ptr field of the php_stream_notifier struct is now a void* instead + of a zval. If the zval was used to store IS_PTR values only, the + extra layer of indirection can be removed. In other cases a zval can + be heap-allocated and stored in the pointer as a minimal change to keep + compatibility. + . The validator callbacks for internal attribute now return `zend_string *` + rather than `void`; instead of emitting an error when an attribute is + applied incorrectly, the error message should be returned as a zend_string + pointer. If the error will be delayed until runtime, it is stored in the + new `validation_error` field of the `zend_attribute` struct. + RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute . Added zend_safe_assign_to_variable_noref() function to safely assign a value to a non-reference zval. . Added zval_ptr_safe_dtor() to safely destroy a zval when a destructor @@ -43,67 +51,129 @@ PHP 8.5 INTERNALS UPGRADE NOTES . Added the zend_update_exception_properties() function for instantiating Exception child classes. It updates the $message, $code, and $previous properties. + . zend_exception_get_default() was removed, use zend_ce_exception directly. + . zend_get_error_exception() was removed, use zend_ce_error_exception + directly. . ZEND_IS_XDIGIT() macro was removed because it was unused and its name did not match its actual behavior. + . The following zend_string-related legacy aliases were removed: + * IS_INTERNED() - use ZSTR_IS_INTERNED() + * STR_EMPTY_ALLOC() - use ZSTR_EMPTY_ALLOC() + * _STR_HEADER_SIZE - use _ZSTR_HEADER_SIZE + * STR_ALLOCA_ALLOC() - use ZSTR_ALLOCA_ALLOC() + * STR_ALLOCA_INIT() - use ZSTR_ALLOCA_INIT() + * STR_ALLOCA_FREE() - use ZSTR_ALLOCA_FREE() + . zend_register_constant() now returns a pointer to the added constant + on success and NULL on failure instead of SUCCESS/FAILURE. + The specialized registration methods that previously had void returns + also return pointers to the added constants: + * zend_register_bool_constant() + * zend_register_null_constant() + * zend_register_long_constant() + * zend_register_double_constant() + * zend_register_string_constant() + * zend_register_stringl_constant() + . EG(fake_scope) now is a _const_ zend_class_entry*. + . zend_begin_record_errors() or EG(record_errors)=true cause errors to be + delayed. Before, errors would be recorded but not delayed. + . zend_mm_refresh_key_child() must be called on any zend_mm_heap inherited + from the parent process after a fork(). + . HASH_KEY_IS_* constants have been moved in the zend_hash_key_type enum. ======================== 2. Build system changes ======================== +- Abstract + . Preprocessor macro SIZEOF_PTRDIFF_T has been removed. + . Preprocessor macro SIZEOF_INTMAX_T has been removed. + - Windows build system changes - . SAPI() and ADD_SOURCES() now suport the optional `duplicate_sources` + . SAPI() and ADD_SOURCES() now support the optional `duplicate_sources` parameter. If truthy, no rules to build the object files are generated. This allows to build additional variants of SAPIs (e.g. a DLL and EXE) without duplicate build rules. It is up to the SAPI maintainers to ensure that appropriate build rules are created. - Unix build system changes - . libdir is properly set when --libdir (ex: /usr/lib64) and --with-libdir (ex lib64) + . libdir is properly set when --libdir (ex: /usr/lib64) and --with-libdir (ex: lib64) configure options are used to ${libdir}/php (ex: /usr/lib64/php) . PHP_ODBC_CFLAGS, PHP_ODBC_LFLAGS, PHP_ODBC_LIBS, PHP_ODBC_TYPE preprocessor macros defined by ext/odbc are now defined in php_config.h instead of the build-defs.h header. + . Autoconf macro AX_CHECK_COMPILE_FLAG updated to serial 11. . Autoconf macro PHP_AP_EXTRACT_VERSION has been removed. . Autoconf macro PHP_BUILD_THREAD_SAFE has been removed (set enable_zts manually). + . Autoconf macro PHP_CHECK_SIZEOF is obsolete (use AC_CHECK_SIZEOF). . Autoconf macro PHP_DEF_HAVE has been removed (use AC_DEFINE). . Autoconf macro PHP_OUTPUT has been removed (use AC_CONFIG_FILES). . Autoconf macro PHP_TEST_BUILD has been removed (use AC_* macros). + . Preprocessor macro HAVE_PTRDIFF_T has been removed. + . Preprocessor macro HAVE_INTMAX_T has been removed. + . Preprocessor macro HAVE_SSIZE_T has been removed. + . Preprocessor macro SIZEOF_SSIZE_T has been removed. ======================== 3. Module changes ======================== -- ext/gd +- Gd: . The gdImageScale*() and gdImageRotate*() helpers are now internal in the bundled libgd, like they have been in external libgd as of gd-2.1.1. -- ext/json +- Hash: + . Hash functions now use proper hash_spec_result enum for return values + instead of using SUCCESS and FAILURE. + +- JSON: . php_json_encode_serializable_object() now assumes `EG(active)`, if not a bailout is caused. Therefore a minor BC break exists if the `PHP_JSON_PARTIAL_OUTPUT_ON_ERROR` option is in use. However, this situation is highly unlikely. -- ext/libxml +- Libxml: . The refcount APIs now return an `unsigned int` instead of an `int`. . Removed php_libxml_xmlCheckUTF8(). Use xmlCheckUTF8() from libxml instead. -- ext/pdo +- PDO: . Added `php_pdo_stmt_valid_db_obj_handle()` to check if the database object is still valid. This is useful when a GC cycle is collected and the database object can be destroyed prior to destroying the statement. -- ext/standard +- Random: + . The handlers parameter of php_random_engine_common_init() has been + removed. Use the default_object_handlers field on the CE instead. + +- Standard: . Added php_url_decode_ex() and php_raw_url_decode_ex() that unlike their non-ex counterparts do not work in-place. . The php_std_date() function has been removed. Use php_format_date() with the "D, d M Y H:i:s \\G\\M\\T" format instead. . Added php_url_encode_to_smart_str() to encode a URL to a smart_str buffer. + . The functionality of getimagesize(), image_type_to_mime_type(), + and image_type_to_extension() is now extensible using the internal APIs + php_image_register_handler() and php_image_unregister_handler() in + php_image.h. + . ext/standard/php_smart_string.h and ext/standard/php_smart_string_public.h + were removed. Use the corresponding headers in Zend/ instead. + +- URI: + . Internal API for URI handling was added via the php_uri_*() functions. ======================== 4. OpCode changes ======================== +* New ZEND_DECLARE_ATTRIBUTED_CONST is used when a global constant is declared + with `const` and has attributes; this opcode is used *instead* of the + ZEND_DECLARE_CONST, and in addition to the name of the constant and the + value to use, has a ZEND_OP_DATA with a pointer to the compiled attributes. + ======================== 5. SAPI changes ======================== + +- SAPIs must now call php_child_init() after a fork. If php-src code was + executed in other threads than the one initiating the fork, + refresh_memory_manager() must be called in every such thread. diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 96a0e81f03825..275c519d431be 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -420,6 +420,14 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array } break; + case ZEND_EXT_STMT: + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + /* Variable will be deleted later by FREE, so we can't optimize it */ + Tsource[VAR_NUM(opline->op1.var)] = NULL; + break; + } + break; + case ZEND_CASE: case ZEND_CASE_STRICT: case ZEND_COPY_TMP: diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index c86672a8dd248..c1faf2a3fbe03 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -838,9 +838,7 @@ static inline zend_result ct_eval_func_call_ex( zval_ptr_dtor(result); zend_clear_exception(); retval = FAILURE; - } - - if (EG(capture_warnings_during_sccp) > 1) { + } else if (EG(capture_warnings_during_sccp) > 1) { zval_ptr_dtor(result); retval = FAILURE; } diff --git a/Zend/Optimizer/zend_dump.c b/Zend/Optimizer/zend_dump.c index 4e46b38a8eb5e..64deb7085edf3 100644 --- a/Zend/Optimizer/zend_dump.c +++ b/Zend/Optimizer/zend_dump.c @@ -1164,7 +1164,7 @@ ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_fl } if (op_array->try_catch_array[i].finally_end) { fprintf(stderr, - ", %04u", + ", %04u\n", op_array->try_catch_array[i].finally_end); } else { fprintf(stderr, ", -\n"); diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index c36b7490de62c..b7b118c710c53 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -131,9 +131,7 @@ static const func_info_t func_infos[] = { F1("imagecreatefromgd", MAY_BE_OBJECT|MAY_BE_FALSE), F1("imagecreatefromgd2", MAY_BE_OBJECT|MAY_BE_FALSE), F1("imagecreatefromgd2part", MAY_BE_OBJECT|MAY_BE_FALSE), -#if defined(HAVE_GD_BMP) F1("imagecreatefrombmp", MAY_BE_OBJECT|MAY_BE_FALSE), -#endif F1("imagecolorsforindex", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG), F1("imagegetclip", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_LONG), #if defined(HAVE_GD_FREETYPE) @@ -395,8 +393,6 @@ static const func_info_t func_infos[] = { 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), - 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), FN("array_values", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), F1("array_count_values", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG), @@ -405,13 +401,8 @@ static const func_info_t func_infos[] = { F1("array_flip", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING), F1("array_change_key_case", 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_intersect_key", 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_intersect_ukey", 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_intersect", 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_uintersect", 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_intersect_assoc", 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_uintersect_assoc", 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_intersect_uassoc", 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_uintersect_uassoc", 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_diff_key", 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_diff_ukey", 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_udiff", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF), @@ -519,7 +510,7 @@ static const func_info_t func_infos[] = { F1("getcwd", MAY_BE_STRING|MAY_BE_FALSE), F1("readdir", MAY_BE_STRING|MAY_BE_FALSE), F1("scandir", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), - F1("glob", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), + FN("glob", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_FALSE), F1("exec", MAY_BE_STRING|MAY_BE_FALSE), F1("system", MAY_BE_STRING|MAY_BE_FALSE), F1("escapeshellcmd", MAY_BE_STRING), diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index fc6b9b421b628..62e04cb0e306b 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -1623,12 +1623,16 @@ static bool zend_inference_widening_meet(zend_ssa_var_info *var_info, zend_ssa_r r->min < var_info->range.min) { r->underflow = 1; r->min = ZEND_LONG_MIN; + } else { + r->min = var_info->range.min; } if (r->overflow || var_info->range.overflow || r->max > var_info->range.max) { r->overflow = 1; r->max = ZEND_LONG_MAX; + } else { + r->max = var_info->range.max; } if (var_info->range.min == r->min && var_info->range.max == r->max && @@ -2409,7 +2413,7 @@ static const zend_property_info *lookup_prop_info(const zend_class_entry *ce, ze /* If the class is linked, reuse the precise runtime logic. */ if ((ce->ce_flags & ZEND_ACC_LINKED) && (!scope || (scope->ce_flags & ZEND_ACC_LINKED))) { - zend_class_entry *prev_scope = EG(fake_scope); + const zend_class_entry *prev_scope = EG(fake_scope); EG(fake_scope) = scope; prop_info = zend_get_property_info(ce, name, 1); EG(fake_scope) = prev_scope; diff --git a/Zend/Optimizer/zend_optimizer.h b/Zend/Optimizer/zend_optimizer.h index 16bfd75520d89..43a0f60a23219 100644 --- a/Zend/Optimizer/zend_optimizer.h +++ b/Zend/Optimizer/zend_optimizer.h @@ -98,6 +98,10 @@ ZEND_API int zend_optimizer_register_pass(zend_optimizer_pass_t pass); ZEND_API void zend_optimizer_unregister_pass(int idx); zend_result zend_optimizer_startup(void); zend_result zend_optimizer_shutdown(void); + +typedef void (*zend_op_array_func_t)(zend_op_array *, void *context); +void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void *context); + END_EXTERN_C() #endif diff --git a/Zend/Optimizer/zend_optimizer_internal.h b/Zend/Optimizer/zend_optimizer_internal.h index a1fc57092d179..896fe8fb47289 100644 --- a/Zend/Optimizer/zend_optimizer_internal.h +++ b/Zend/Optimizer/zend_optimizer_internal.h @@ -128,7 +128,4 @@ int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zen int dce_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *optimizer_ctx, zend_ssa *ssa, bool reorder_dtor_effects); zend_result zend_ssa_escape_analysis(const zend_script *script, zend_op_array *op_array, zend_ssa *ssa); -typedef void (*zend_op_array_func_t)(zend_op_array *, void *context); -void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void *context); - #endif diff --git a/Zend/Optimizer/zend_ssa.c b/Zend/Optimizer/zend_ssa.c index 4c09e5e105b50..886bb467b444f 100644 --- a/Zend/Optimizer/zend_ssa.c +++ b/Zend/Optimizer/zend_ssa.c @@ -22,6 +22,7 @@ #include "zend_ssa.h" #include "zend_dump.h" #include "zend_inference.h" +#include "zend_worklist.h" #include "Optimizer/zend_optimizer_internal.h" static bool dominates(const zend_basic_block *blocks, int a, int b) { @@ -816,7 +817,7 @@ ZEND_API int zend_ssa_rename_op(const zend_op_array *op_array, const zend_op *op } /* }}} */ -static zend_result zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, int *var, int n) /* {{{ */ +static void zend_ssa_rename_in_block(const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, int *var, int n) /* {{{ */ { zend_basic_block *blocks = ssa->cfg.blocks; zend_ssa_block *ssa_blocks = ssa->blocks; @@ -824,15 +825,6 @@ static zend_result zend_ssa_rename(const zend_op_array *op_array, uint32_t build int ssa_vars_count = ssa->vars_count; int i, j; zend_op *opline, *end; - int *tmp = NULL; - ALLOCA_FLAG(use_heap = 0); - - // FIXME: Can we optimize this copying out in some cases? - if (blocks[n].next_child >= 0) { - tmp = do_alloca(sizeof(int) * (op_array->last_var + op_array->T), use_heap); - memcpy(tmp, var, sizeof(int) * (op_array->last_var + op_array->T)); - var = tmp; - } if (ssa_blocks[n].phis) { zend_ssa_phi *phi = ssa_blocks[n].phis; @@ -916,22 +908,90 @@ static zend_result zend_ssa_rename(const zend_op_array *op_array, uint32_t build } ssa->vars_count = ssa_vars_count; +} +/* }}} */ - j = blocks[n].children; - while (j >= 0) { - // FIXME: Tail call optimization? - if (zend_ssa_rename(op_array, build_flags, ssa, var, j) == FAILURE) - return FAILURE; - j = blocks[j].next_child; +static zend_result zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, int *var, int n) +{ + /* The worklist contains block numbers, encoded as positive or negative value. + * Positive values indicate that the variable rename still needs to happen for the block. + * Negative values indicate the variable rename was done and all children were handled too. + * In that case, we will clean up. + * Because block 0 is valid, we bias the block numbers by adding 1 such that we can distinguish + * positive and negative values in all cases. */ + zend_worklist_stack work; + ALLOCA_FLAG(work_use_heap); + ZEND_WORKLIST_STACK_ALLOCA(&work, ssa->cfg.blocks_count, work_use_heap); + zend_worklist_stack_push(&work, n + 1); + + /* This is used to backtrack the right version of the renamed variables to use. */ + ALLOCA_FLAG(save_vars_use_heap); + unsigned int save_vars_top = 0; + int **save_vars = do_alloca(sizeof(int *) * (ssa->cfg.blocks_count + 1), save_vars_use_heap); + save_vars[0] = var; + + while (work.len) { + n = zend_worklist_stack_pop(&work); + + /* Enter state: perform SSA variable rename */ + if (n > 0) { + n--; + + // FIXME: Can we optimize this copying out in some cases? + int *new_var; + if (ssa->cfg.blocks[n].next_child >= 0) { + new_var = emalloc(sizeof(int) * (op_array->last_var + op_array->T)); + memcpy(new_var, save_vars[save_vars_top], sizeof(int) * (op_array->last_var + op_array->T)); + save_vars[++save_vars_top] = new_var; + } else { + new_var = save_vars[save_vars_top]; + } + + zend_ssa_rename_in_block(op_array, build_flags, ssa, new_var, n); + + int j = ssa->cfg.blocks[n].children; + if (j >= 0) { + /* Push backtrack state */ + zend_worklist_stack_push(&work, -(n + 1)); + + /* Push children in enter state */ + unsigned int child_count = 0; + int len_prior = work.len; + do { + zend_worklist_stack_push(&work, j + 1); + j = ssa->cfg.blocks[j].next_child; + child_count++; + } while (j >= 0); + + /* Reverse block order to maintain SSA variable number order given in previous PHP versions, + * but the data structure doesn't allow reverse dominator tree traversal. */ + for (unsigned int i = 0; i < child_count / 2; i++) { + int tmp = work.buf[len_prior + i]; + work.buf[len_prior + i] = work.buf[work.len - 1 - i]; + work.buf[work.len - 1 - i] = tmp; + } + } else { + /* Leafs jump directly to backtracking */ + goto backtrack; + } + } + /* Leave state: backtrack */ + else { + n = -n; + n--; +backtrack:; + if (ssa->cfg.blocks[n].next_child >= 0) { + efree(save_vars[save_vars_top]); + save_vars_top--; + } + } } - if (tmp) { - free_alloca(tmp, use_heap); - } + free_alloca(save_vars, save_vars_use_heap); + ZEND_WORKLIST_STACK_FREE_ALLOCA(&work, work_use_heap); return SUCCESS; } -/* }}} */ ZEND_API zend_result zend_build_ssa(zend_arena **arena, const zend_script *script, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa) /* {{{ */ { diff --git a/Zend/Zend.m4 b/Zend/Zend.m4 index 45791a34c5f80..1e1853167cfe3 100644 --- a/Zend/Zend.m4 +++ b/Zend/Zend.m4 @@ -149,6 +149,7 @@ AC_CHECK_FUNCS(m4_normalize([ pthread_get_stackaddr_np pthread_getattr_np pthread_stackseg_np + strnlen ])) AC_CHECK_DECL([clock_gettime_nsec_np], @@ -169,6 +170,7 @@ ZEND_CHECK_STACK_DIRECTION ZEND_CHECK_FLOAT_PRECISION ZEND_DLSYM_CHECK ZEND_CHECK_GLOBAL_REGISTER_VARIABLES +ZEND_CHECK_PRESERVE_NONE ZEND_CHECK_CPUID_COUNT AC_MSG_CHECKING([whether to enable thread safety]) @@ -192,28 +194,21 @@ AS_VAR_IF([GCC], [yes], dnl Check if compiler supports -Wno-clobbered (only GCC). AX_CHECK_COMPILE_FLAG([-Wno-clobbered], - [CFLAGS="-Wno-clobbered $CFLAGS"],, - [-Werror]) + [CFLAGS="-Wno-clobbered $CFLAGS"]) dnl Check for support for implicit fallthrough level 1, also add after previous dnl CFLAGS as level 3 is enabled in -Wextra. AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough=1], - [CFLAGS="$CFLAGS -Wimplicit-fallthrough=1"],, - [-Werror]) + [CFLAGS="$CFLAGS -Wimplicit-fallthrough=1"]) AX_CHECK_COMPILE_FLAG([-Wduplicated-cond], - [CFLAGS="-Wduplicated-cond $CFLAGS"],, - [-Werror]) + [CFLAGS="-Wduplicated-cond $CFLAGS"]) AX_CHECK_COMPILE_FLAG([-Wlogical-op], - [CFLAGS="-Wlogical-op $CFLAGS"],, - [-Werror]) + [CFLAGS="-Wlogical-op $CFLAGS"]) AX_CHECK_COMPILE_FLAG([-Wformat-truncation], - [CFLAGS="-Wformat-truncation $CFLAGS"],, - [-Werror]) + [CFLAGS="-Wformat-truncation $CFLAGS"]) AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes], - [CFLAGS="-Wstrict-prototypes $CFLAGS"],, - [-Werror]) + [CFLAGS="-Wstrict-prototypes $CFLAGS"]) AX_CHECK_COMPILE_FLAG([-fno-common], - [CFLAGS="-fno-common $CFLAGS"],, - [-Werror]) + [CFLAGS="-fno-common $CFLAGS"]) ZEND_CHECK_ALIGNMENT ZEND_CHECK_SIGNALS @@ -470,3 +465,103 @@ AS_VAR_IF([ZEND_MAX_EXECUTION_TIMERS], [yes], AC_MSG_CHECKING([whether to enable Zend max execution timers]) AC_MSG_RESULT([$ZEND_MAX_EXECUTION_TIMERS]) ]) + +dnl +dnl ZEND_CHECK_PRESERVE_NONE +dnl +dnl Check if the preserve_none calling convention is supported and matches our +dnl expectations. +dnl +AC_DEFUN([ZEND_CHECK_PRESERVE_NONE], [dnl + AC_CACHE_CHECK([for preserve_none calling convention], + [php_cv_preverve_none], + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include + +const char * const1 = "str1"; +const char * const2 = "str2"; +const char * const3 = "str3"; +uint64_t key = UINT64_C(0x9d7f71d2bd296364); + +uintptr_t _a = 0; +uintptr_t _b = 0; + +uintptr_t __attribute__((preserve_none)) fun(uintptr_t a, uintptr_t b) { + _a = a; + _b = b; + return (uintptr_t)const3; +} + +uintptr_t __attribute__((preserve_none)) test(void) { + uintptr_t ret; + +#if defined(__x86_64__) + __asm__ __volatile__( + /* XORing to make it unlikely the value exists in any other register */ + "movq %1, %%r12\n" + "xorq %3, %%r12\n" + "movq %2, %%r13\n" + "xorq %3, %%r13\n" + "xorq %%rax, %%rax\n" + "call fun\n" + : "=a" (ret) + : "r" (const1), "r" (const2), "r" (key) + : "r12", "r13" + ); +#elif defined(__aarch64__) + __asm__ __volatile__( + /* XORing to make it unlikely the value exists in any other register */ + "eor x20, %1, %3\n" + "eor x21, %2, %3\n" + "eor x0, x0, x0\n" + "bl fun\n" + "mov %0, x0\n" + : "=r" (ret) + : "r" (const1), "r" (const2), "r" (key) + : "x0", "x21", "x22", "x30" + ); +#else +# error +#endif + + return ret; +} + +int main(void) { + + /* JIT is making the following expectations about preserve_none: + * - The registers used for integer args 1 and 2 + * - The register used for a single integer return value + * + * We check these expectations here: + */ + + uintptr_t ret = test(); + + if (_a != ((uintptr_t)const1 ^ key)) { + fprintf(stderr, "arg1 mismatch\n"); + return 1; + } + if (_b != ((uintptr_t)const2 ^ key)) { + fprintf(stderr, "arg2 mismatch\n"); + return 2; + } + if (ret != (uintptr_t)const3) { + fprintf(stderr, "ret mismatch\n"); + return 3; + } + + fprintf(stderr, "OK\n"); + + return 0; +}]])], + [php_cv_preserve_none=yes], + [php_cv_preserve_none=no], + [php_cv_preserve_none=no]) + ]) + AS_VAR_IF([php_cv_preserve_none], [yes], [ + AC_DEFINE([HAVE_PRESERVE_NONE], [1], + [Define to 1 if you have preserve_none support.]) + ]) +]) diff --git a/Zend/tests/014.inc b/Zend/tests/014.inc deleted file mode 100644 index 69c9bc0790257..0000000000000 --- a/Zend/tests/014.inc +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/Zend/tests/022.phpt b/Zend/tests/abstract_method_optional_params.phpt similarity index 100% rename from Zend/tests/022.phpt rename to Zend/tests/abstract_method_optional_params.phpt diff --git a/Zend/tests/arginfo_zpp_mismatch.inc b/Zend/tests/arginfo_zpp_mismatch.inc index 5b2711fdb6303..2eb8905f5d4a1 100644 --- a/Zend/tests/arginfo_zpp_mismatch.inc +++ b/Zend/tests/arginfo_zpp_mismatch.inc @@ -9,6 +9,7 @@ function skipFunction($function): bool { /* terminates script */ || $function === 'exit' || $function === 'die' + || $function === 'zend_trigger_bailout' /* intentionally violate invariants */ || $function === 'zend_create_unterminated_string' || $function === 'zend_test_array_return' diff --git a/Zend/tests/032.phpt b/Zend/tests/array_append_by_reference.phpt similarity index 100% rename from Zend/tests/032.phpt rename to Zend/tests/array_append_by_reference.phpt diff --git a/Zend/tests/031.phpt b/Zend/tests/array_append_reading_error.phpt similarity index 100% rename from Zend/tests/031.phpt rename to Zend/tests/array_append_reading_error.phpt diff --git a/Zend/tests/array_unpack/gh19303.phpt b/Zend/tests/array_unpack/gh19303.phpt new file mode 100644 index 0000000000000..af594c3740c2d --- /dev/null +++ b/Zend/tests/array_unpack/gh19303.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-19303 (Unpacking empty packed array into uninitialized array causes assertion failure) +--FILE-- + +--EXPECT-- +array(0) { +} diff --git a/Zend/tests/arrow_functions/gh7900.phpt b/Zend/tests/arrow_functions/gh7900.phpt index a4170fb1278fc..d6465c312399c 100644 --- a/Zend/tests/arrow_functions/gh7900.phpt +++ b/Zend/tests/arrow_functions/gh7900.phpt @@ -23,4 +23,4 @@ try { ?> --EXPECT-- Here -assert(fn(): never => 42 && false) +assert((fn(): never => 42) && false) diff --git a/Zend/tests/assert/expect_012.phpt b/Zend/tests/assert/expect_012.phpt index 71e2f96e629a4..77a5e48528473 100644 --- a/Zend/tests/assert/expect_012.phpt +++ b/Zend/tests/assert/expect_012.phpt @@ -5,12 +5,12 @@ zend.assertions=1 assert.exception=1 --FILE-- diff --git a/Zend/tests/029.phpt b/Zend/tests/assign_array_object_property.phpt similarity index 100% rename from Zend/tests/029.phpt rename to Zend/tests/assign_array_object_property.phpt diff --git a/Zend/tests/assign_dim_op_undef.phpt b/Zend/tests/assign_dim_op_undef.phpt index 187aed97857a4..346311235435c 100644 --- a/Zend/tests/assign_dim_op_undef.phpt +++ b/Zend/tests/assign_dim_op_undef.phpt @@ -10,6 +10,8 @@ Warning: Undefined variable $a in %s on line %d Warning: Undefined variable $b in %s on line %d +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d + Warning: Undefined array key "" in %s on line %d array(1) { [""]=> diff --git a/Zend/tests/026.phpt b/Zend/tests/assign_property_null_object.phpt similarity index 100% rename from Zend/tests/026.phpt rename to Zend/tests/assign_property_null_object.phpt diff --git a/Zend/tests/asymmetric_visibility/gh19044.phpt b/Zend/tests/asymmetric_visibility/gh19044.phpt new file mode 100644 index 0000000000000..253e315d5b945 --- /dev/null +++ b/Zend/tests/asymmetric_visibility/gh19044.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (protected(set) on non-hooked property) +--FILE-- + 42; } +} + +class C1 extends P { + public protected(set) mixed $foo = 1; +} + +class C2 extends P { + public protected(set) mixed $foo; + + static function foo($c) { return $c->foo += 1; } +} + +var_dump(C2::foo(new C1)); + +?> +--EXPECT-- +int(43) diff --git a/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt b/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt new file mode 100644 index 0000000000000..547946c4e1300 --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_abstract.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on an abstract class +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply #[\Attribute] to abstract class Demo in %s on line %d diff --git a/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt b/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt new file mode 100644 index 0000000000000..c5545054dcff3 --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_enum.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on an enum +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply #[\Attribute] to enum Demo in %s on line %d diff --git a/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt b/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt new file mode 100644 index 0000000000000..4b9a87a2395d8 --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_interface.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on an interface +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply #[\Attribute] to interface Demo in %s on line %d diff --git a/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt b/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt new file mode 100644 index 0000000000000..7ea05543baa29 --- /dev/null +++ b/Zend/tests/attributes/Attribute/Attribute_on_trait.phpt @@ -0,0 +1,12 @@ +--TEST-- +#[Attribute] on a trait +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply #[\Attribute] to trait Demo in %s on line %d diff --git a/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt b/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt index b9ab745be9ae7..f1ce8b055b0e0 100644 --- a/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt +++ b/Zend/tests/attributes/allow_dynamic_properties_on_enum.phpt @@ -8,4 +8,4 @@ enum Test {} ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to enum Test in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to enum Test in %s on line %d diff --git a/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt b/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt index 0428256a18e40..16440a385db14 100644 --- a/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt +++ b/Zend/tests/attributes/allow_dynamic_properties_on_interface.phpt @@ -8,4 +8,4 @@ interface Test {} ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to interface Test in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to interface Test in %s on line %d diff --git a/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt b/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt index 9636dc03141e5..bd18b3e71c8f1 100644 --- a/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt +++ b/Zend/tests/attributes/allow_dynamic_properties_on_trait.phpt @@ -8,4 +8,4 @@ trait Test {} ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to trait Test in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to trait Test in %s on line %d diff --git a/Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt b/Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt index b0b88c2f6edab..8a979095e7b95 100644 --- a/Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt +++ b/Zend/tests/attributes/constants/constant_listed_as_target-internal.phpt @@ -3,9 +3,10 @@ Constants listed in valid targets when used wrong (internal attribute) --FILE-- --EXPECTF-- -Fatal error: Attribute "Deprecated" cannot target class (allowed targets: function, method, class constant, constant) in %s on line %d +Fatal error: Attribute "Deprecated" cannot target parameter (allowed targets: class, function, method, class constant, constant) in %s on line %d diff --git a/Zend/tests/attributes/constants/constant_redefined_addition.phpt b/Zend/tests/attributes/constants/constant_redefined_addition.phpt index 08f9670989627..5831332afdc5b 100644 --- a/Zend/tests/attributes/constants/constant_redefined_addition.phpt +++ b/Zend/tests/attributes/constants/constant_redefined_addition.phpt @@ -15,7 +15,7 @@ var_dump($reflection->getAttributes()) ?> --EXPECTF-- -Warning: Constant MY_CONST already defined in %s on line %d +Warning: Constant MY_CONST already defined, this will be an error in PHP 9 in %s on line %d No attributes array(0) { } diff --git a/Zend/tests/attributes/constants/constant_redefined_change.phpt b/Zend/tests/attributes/constants/constant_redefined_change.phpt index 158753ee07d84..1682f9c2a2996 100644 --- a/Zend/tests/attributes/constants/constant_redefined_change.phpt +++ b/Zend/tests/attributes/constants/constant_redefined_change.phpt @@ -16,7 +16,7 @@ var_dump($reflection->getAttributes()) ?> --EXPECTF-- -Warning: Constant MY_CONST already defined in %s on line %d +Warning: Constant MY_CONST already defined, this will be an error in PHP 9 in %s on line %d Has attributes (1) array(1) { [0]=> diff --git a/Zend/tests/attributes/constants/constant_redefined_removal.phpt b/Zend/tests/attributes/constants/constant_redefined_removal.phpt index 0b679a55985e3..45476ab6f000c 100644 --- a/Zend/tests/attributes/constants/constant_redefined_removal.phpt +++ b/Zend/tests/attributes/constants/constant_redefined_removal.phpt @@ -15,7 +15,7 @@ var_dump($reflection->getAttributes()) ?> --EXPECTF-- -Warning: Constant MY_CONST already defined in %s on line %d +Warning: Constant MY_CONST already defined, this will be an error in PHP 9 in %s on line %d Has attributes array(1) { [0]=> diff --git a/Zend/tests/attributes/constants/multiple_constants_error.phpt b/Zend/tests/attributes/constants/multiple_constants_error.phpt index d4258c9f4d080..b7ee91d3f1d97 100644 --- a/Zend/tests/attributes/constants/multiple_constants_error.phpt +++ b/Zend/tests/attributes/constants/multiple_constants_error.phpt @@ -5,7 +5,9 @@ Error trying to add attributes to multiple constants at once #[\Foo] const First = 1, - Second = 2; + Second = 2, + Third = 3, + Fourth = 4; ?> --EXPECTF-- diff --git a/Zend/tests/attributes/constants/oss_fuzz_428053935.phpt b/Zend/tests/attributes/constants/oss_fuzz_428053935.phpt new file mode 100644 index 0000000000000..97747fd6194fd --- /dev/null +++ b/Zend/tests/attributes/constants/oss_fuzz_428053935.phpt @@ -0,0 +1,19 @@ +--TEST-- +OSS-Fuzz #428053935 +--FILE-- +getAttributes()); +?> +--EXPECTF-- +array(1) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(8) "Foo\Attr" + } +} diff --git a/Zend/tests/attributes/delayed_target_validation/has_runtime_errors.phpt b/Zend/tests/attributes/delayed_target_validation/has_runtime_errors.phpt new file mode 100644 index 0000000000000..b1efb538b328b --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/has_runtime_errors.phpt @@ -0,0 +1,282 @@ +--TEST-- +#[\DelayedTargetValidation] has errors at runtime +--FILE-- + $this->v2; + #[DelayedTargetValidation] + #[Attribute] + set => $value; + } + + #[DelayedTargetValidation] + #[Attribute] + public function __construct( + #[DelayedTargetValidation] + #[Attribute] + public string $v3 + ) { + $this->v1 = $v3; + echo __METHOD__ . "\n"; + } +} + +#[DelayedTargetValidation] +#[Attribute] +function demoFn() { + echo __FUNCTION__ . "\n"; +} + +#[DelayedTargetValidation] +#[Attribute] +const EXAMPLE = true; + +$cases = [ + new ReflectionClass('Demo'), + new ReflectionClassConstant('Demo', 'FOO'), + new ReflectionProperty('Demo', 'v1'), + new ReflectionProperty('Demo', 'v2')->getHook(PropertyHookType::Get), + new ReflectionProperty('Demo', 'v2')->getHook(PropertyHookType::Set), + new ReflectionMethod('Demo', '__construct'), + new ReflectionParameter([ 'Demo', '__construct' ], 'v3'), + new ReflectionProperty('Demo', 'v3'), + new ReflectionFunction('demoFn'), + new ReflectionConstant('EXAMPLE'), +]; +foreach ($cases as $r) { + echo str_repeat("*", 20) . "\n"; + echo $r . "\n"; + $attributes = $r->getAttributes(); + var_dump($attributes); + try { + $attributes[1]->newInstance(); + } catch (Error $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; + } +} + +?> +--EXPECTF-- +******************** +Class [ class Demo ] { + @@ %s %d-%d + + - Constants [1] { + Constant [ public string FOO ] { BAR } + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [3] { + Property [ public string $v1 ] + Property [ public string $v2 { get; set; } ] + Property [ public string $v3 ] + } + + - Methods [1] { + Method [ public method __construct ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ string $v3 ] + } + } + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "NoDiscard" + } +} +Error: Attribute "NoDiscard" cannot target class (allowed targets: function, method) +******************** +Constant [ public string FOO ] { BAR } + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target class constant (allowed targets: class) +******************** +Property [ public string $v1 ] + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target property (allowed targets: class) +******************** +Method [ public method $v2::get ] { + @@ %s %d - %d + + - Parameters [0] { + } + - Return [ string ] +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target method (allowed targets: class) +******************** +Method [ public method $v2::set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ string $value ] + } + - Return [ void ] +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target method (allowed targets: class) +******************** +Method [ public method __construct ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ string $v3 ] + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target method (allowed targets: class) +******************** +Parameter #0 [ string $v3 ] +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target parameter (allowed targets: class) +******************** +Property [ public string $v3 ] + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target property (allowed targets: class) +******************** +Function [ function demoFn ] { + @@ %s %d - %d +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target function (allowed targets: class) +******************** +Constant [ bool EXAMPLE ] { 1 } + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Attribute "Attribute" cannot target constant (allowed targets: class) diff --git a/Zend/tests/attributes/delayed_target_validation/no_compile_errors.phpt b/Zend/tests/attributes/delayed_target_validation/no_compile_errors.phpt new file mode 100644 index 0000000000000..b2e14a235f8a5 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/no_compile_errors.phpt @@ -0,0 +1,55 @@ +--TEST-- +#[\DelayedTargetValidation] prevents target errors at compile time +--FILE-- + $this->v2; + #[DelayedTargetValidation] + #[Attribute] + set => $value; + } + + #[DelayedTargetValidation] + #[Attribute] + public function __construct( + #[DelayedTargetValidation] + #[Attribute] + public string $v3 + ) { + $this->v1 = $v3; + echo __METHOD__ . "\n"; + } +} + +#[DelayedTargetValidation] +#[Attribute] +function demoFn() { + echo __FUNCTION__ . "\n"; +} + +$o = new Demo( "foo" ); +demoFn(); + +#[DelayedTargetValidation] +#[Attribute] +const EXAMPLE = true; + +?> +--EXPECT-- +Demo::__construct +demoFn diff --git a/Zend/tests/attributes/delayed_target_validation/opcache_validator_errors.inc b/Zend/tests/attributes/delayed_target_validation/opcache_validator_errors.inc new file mode 100644 index 0000000000000..275df500c7e93 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/opcache_validator_errors.inc @@ -0,0 +1,5 @@ + +--FILE-- +getAttributes(); +var_dump($attributes); +try { + $attributes[1]->newInstance(); +} catch (Error $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +?> +--EXPECTF-- +Trait [ trait DemoTrait ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(22) "AllowDynamicProperties" + } +} +Error: Cannot apply #[\AllowDynamicProperties] to trait DemoTrait diff --git a/Zend/tests/attributes/delayed_target_validation/repetition_errors.phpt b/Zend/tests/attributes/delayed_target_validation/repetition_errors.phpt new file mode 100644 index 0000000000000..5c8f9bfc9dde2 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/repetition_errors.phpt @@ -0,0 +1,13 @@ +--TEST-- +#[\DelayedTargetValidation] does not prevent repetition errors +--FILE-- + +--EXPECTF-- +Fatal error: Attribute "NoDiscard" must not be repeated in %s on line %d diff --git a/Zend/tests/attributes/delayed_target_validation/validator_AllowDynamicProperties.phpt b/Zend/tests/attributes/delayed_target_validation/validator_AllowDynamicProperties.phpt new file mode 100644 index 0000000000000..63add9e445a91 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/validator_AllowDynamicProperties.phpt @@ -0,0 +1,180 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\AllowDynamicProperties]: validator errors delayed +--FILE-- +getAttributes(); + var_dump($attributes); + try { + $attributes[1]->newInstance(); + } catch (Error $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; + } +} + +?> +--EXPECTF-- +******************** +Trait [ trait DemoTrait ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(22) "AllowDynamicProperties" + } +} +Error: Cannot apply #[\AllowDynamicProperties] to trait DemoTrait +******************** +Interface [ interface DemoInterface ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(22) "AllowDynamicProperties" + } +} +Error: Cannot apply #[\AllowDynamicProperties] to interface DemoInterface +******************** +Class [ readonly class DemoReadonly ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(22) "AllowDynamicProperties" + } +} +Error: Cannot apply #[\AllowDynamicProperties] to readonly class DemoReadonly +******************** +Enum [ enum DemoEnum implements UnitEnum ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [1] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + } + + - Properties [1] { + Property [ public protected(set) readonly string $name ] + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(22) "AllowDynamicProperties" + } +} +Error: Cannot apply #[\AllowDynamicProperties] to enum DemoEnum diff --git a/Zend/tests/attributes/delayed_target_validation/validator_Attribute.phpt b/Zend/tests/attributes/delayed_target_validation/validator_Attribute.phpt new file mode 100644 index 0000000000000..0571024f19ced --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/validator_Attribute.phpt @@ -0,0 +1,180 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Attribute]: validator errors delayed +--FILE-- +getAttributes(); + var_dump($attributes); + try { + $attributes[1]->newInstance(); + } catch (Error $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; + } +} + +?> +--EXPECTF-- +******************** +Trait [ trait DemoTrait ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Cannot apply #[\Attribute] to trait DemoTrait +******************** +Interface [ interface DemoInterface ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Cannot apply #[\Attribute] to interface DemoInterface +******************** +Class [ abstract class DemoAbstract ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Cannot apply #[\Attribute] to abstract class DemoAbstract +******************** +Enum [ enum DemoEnum implements UnitEnum ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [1] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + } + + - Properties [1] { + Property [ public protected(set) readonly string $name ] + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "Attribute" + } +} +Error: Cannot apply #[\Attribute] to enum DemoEnum diff --git a/Zend/tests/attributes/delayed_target_validation/validator_Deprecated.phpt b/Zend/tests/attributes/delayed_target_validation/validator_Deprecated.phpt new file mode 100644 index 0000000000000..f5fedb4ee68e1 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/validator_Deprecated.phpt @@ -0,0 +1,142 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Deprecated]: validator errors delayed +--FILE-- +getAttributes(); + var_dump($attributes); + try { + $attributes[1]->newInstance(); + } catch (Error $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; + } +} + +?> +--EXPECTF-- +******************** +Interface [ interface DemoInterface ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(10) "Deprecated" + } +} +Error: Cannot apply #[\Deprecated] to interface DemoInterface +******************** +Class [ class DemoClass ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(10) "Deprecated" + } +} +Error: Cannot apply #[\Deprecated] to class DemoClass +******************** +Enum [ enum DemoEnum implements UnitEnum ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [1] { + Method [ static public method cases ] { + + - Parameters [0] { + } + - Return [ array ] + } + } + + - Properties [1] { + Property [ public protected(set) readonly string $name ] + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(10) "Deprecated" + } +} +Error: Cannot apply #[\Deprecated] to enum DemoEnum diff --git a/Zend/tests/attributes/delayed_target_validation/validator_NoDiscard.phpt b/Zend/tests/attributes/delayed_target_validation/validator_NoDiscard.phpt new file mode 100644 index 0000000000000..e3cfe9d1c1095 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/validator_NoDiscard.phpt @@ -0,0 +1,79 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\NoDiscard]: validator errors delayed +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[NoDiscard] // Does nothing here + set => $value; + } +} + +$cases = [ + new ReflectionProperty('DemoClass', 'hooked')->getHook(PropertyHookType::Get), + new ReflectionProperty('DemoClass', 'hooked')->getHook(PropertyHookType::Set), +]; +foreach ($cases as $r) { + echo str_repeat("*", 20) . "\n"; + echo $r . "\n"; + $attributes = $r->getAttributes(); + var_dump($attributes); + try { + $attributes[1]->newInstance(); + } catch (Error $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; + } +} + +?> +--EXPECTF-- +******************** +Method [ public method $hooked::get ] { + @@ %s %d - %d + + - Parameters [0] { + } + - Return [ string ] +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "NoDiscard" + } +} +Error: #[\NoDiscard] is not supported for property hooks +******************** +Method [ public method $hooked::set ] { + @@ %s %d - %d + + - Parameters [1] { + Parameter #0 [ string $value ] + } + - Return [ void ] +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(9) "NoDiscard" + } +} +Error: #[\NoDiscard] is not supported for property hooks diff --git a/Zend/tests/attributes/delayed_target_validation/validator_success.phpt b/Zend/tests/attributes/delayed_target_validation/validator_success.phpt new file mode 100644 index 0000000000000..5e2a128dd431a --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/validator_success.phpt @@ -0,0 +1,62 @@ +--TEST-- +#[\DelayedTargetValidation] with a successful validator +--FILE-- +dynamic = true; +var_dump($obj); + +$ref = new ReflectionClass('DemoClass'); +echo $ref . "\n"; +$attributes = $ref->getAttributes(); +var_dump($attributes); +var_dump($attributes[1]->newInstance()); + +?> +--EXPECTF-- +object(DemoClass)#%d (0) { +} +object(DemoClass)#%d (1) { + ["dynamic"]=> + bool(true) +} +Class [ class DemoClass ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [0] { + } + + - Methods [0] { + } +} + +array(2) { + [0]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(23) "DelayedTargetValidation" + } + [1]=> + object(ReflectionAttribute)#%d (1) { + ["name"]=> + string(22) "AllowDynamicProperties" + } +} +object(AllowDynamicProperties)#%d (0) { +} diff --git a/Zend/tests/attributes/delayed_target_validation/with_AllowDynamicProperties.phpt b/Zend/tests/attributes/delayed_target_validation/with_AllowDynamicProperties.phpt new file mode 100644 index 0000000000000..83f738491c57e --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_AllowDynamicProperties.phpt @@ -0,0 +1,81 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\AllowDynamicProperties]: invalid targets don't error +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[AllowDynamicProperties] // Does nothing here + set => $value; + } + + #[DelayedTargetValidation] + #[AllowDynamicProperties] // Does nothing here + public const CLASS_CONST = 'FOO'; + + public function __construct( + #[DelayedTargetValidation] + #[AllowDynamicProperties] // Does nothing here + $str + ) { + echo "Got: $str\n"; + $this->val = $str; + } + + #[DelayedTargetValidation] + #[AllowDynamicProperties] // Does nothing here + public function printVal() { + echo 'Value is: ' . $this->val . "\n"; + } + +} + +#[DelayedTargetValidation] +#[AllowDynamicProperties] // Does nothing here +function demoFn() { + echo __FUNCTION__ . "\n"; + return 456; +} + +#[DelayedTargetValidation] +#[AllowDynamicProperties] // Does nothing here +const GLOBAL_CONST = 'BAR'; + +$d = new DemoClass('example'); +$d->printVal(); +var_dump($d->val); +$d->hooked = "foo"; +var_dump($d->hooked); +var_dump(DemoClass::CLASS_CONST); +demoFn(); +var_dump(GLOBAL_CONST); + +$d->missingProp = 'foo'; +var_dump($d); +?> +--EXPECTF-- +Got: example +Value is: example +string(7) "example" +string(3) "foo" +string(3) "FOO" +demoFn +string(3) "BAR" +object(DemoClass)#%d (3) { + ["val"]=> + string(7) "example" + ["hooked"]=> + string(3) "foo" + ["missingProp"]=> + string(3) "foo" +} diff --git a/Zend/tests/attributes/delayed_target_validation/with_Attribute.phpt b/Zend/tests/attributes/delayed_target_validation/with_Attribute.phpt new file mode 100644 index 0000000000000..edc7d2a7905fb --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_Attribute.phpt @@ -0,0 +1,95 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Attribute]: invalid targets don't error +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[Attribute] // Does nothing here + set => $value; + } + + #[DelayedTargetValidation] + #[Attribute] // Does nothing here + public const CLASS_CONST = 'FOO'; + + public function __construct( + #[DelayedTargetValidation] + #[Attribute] // Does nothing here + $str + ) { + echo "Got: $str\n"; + $this->val = $str; + } + + #[DelayedTargetValidation] + #[Attribute] // Does nothing here + public function printVal() { + echo 'Value is: ' . $this->val . "\n"; + } + +} + +#[DelayedTargetValidation] +#[Attribute] // Does nothing here +function demoFn() { + echo __FUNCTION__ . "\n"; + return 456; +} + +#[DelayedTargetValidation] +#[Attribute] // Does nothing here +const GLOBAL_CONST = 'BAR'; + +$d = new DemoClass('example'); +$d->printVal(); +var_dump($d->val); +$d->hooked = "foo"; +var_dump($d->hooked); +var_dump(DemoClass::CLASS_CONST); +demoFn(); +var_dump(GLOBAL_CONST); + +#[DemoClass('BAZ')] +#[NonAttribute] +class WithDemoAttribs {} + +$ref = new ReflectionClass(WithDemoAttribs::class); +$attribs = $ref->getAttributes(); +var_dump($attribs[0]->newInstance()); +var_dump($attribs[1]->newInstance()); + +?> +--EXPECTF-- +Got: example +Value is: example +string(7) "example" +string(3) "foo" +string(3) "FOO" +demoFn +string(3) "BAR" +Got: BAZ +object(DemoClass)#5 (1) { + ["val"]=> + string(3) "BAZ" + ["hooked"]=> + uninitialized(string) +} + +Fatal error: Uncaught Error: Attempting to use non-attribute class "NonAttribute" as attribute in %s:%d +Stack trace: +#0 %s(%d): ReflectionAttribute->newInstance() +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/delayed_target_validation/with_Deprecated.phpt b/Zend/tests/attributes/delayed_target_validation/with_Deprecated.phpt new file mode 100644 index 0000000000000..e103f9d97389a --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_Deprecated.phpt @@ -0,0 +1,91 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Deprecated]: valid targets are deprecated +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[Deprecated] // Does something here + set => $value; + } + + #[DelayedTargetValidation] + #[Deprecated] // Does something here + public const CLASS_CONST = 'FOO'; + + public function __construct( + #[DelayedTargetValidation] + #[Deprecated] // Does nothing here + $str + ) { + echo "Got: $str\n"; + $this->val = $str; + } + + #[DelayedTargetValidation] + #[Deprecated] // Does something here + public function printVal() { + echo 'Value is: ' . $this->val . "\n"; + return 123; + } +} + +#[DelayedTargetValidation] +#[Deprecated] // Does something here +trait DeprecatedTrait {} + +class WithDeprecatedTrait { + use DeprecatedTrait; +} + +#[DelayedTargetValidation] +#[Deprecated] // Does something here +function demoFn() { + echo __FUNCTION__ . "\n"; + return 456; +} + +#[DelayedTargetValidation] +#[Deprecated] // Does something here +const GLOBAL_CONST = 'BAR'; + +$d = new DemoClass('example'); +$d->printVal(); +var_dump($d->val); +$d->hooked = "foo"; +var_dump($d->hooked); +var_dump(DemoClass::CLASS_CONST); +demoFn(); +var_dump(GLOBAL_CONST); +?> +--EXPECTF-- +Deprecated: Trait DeprecatedTrait used by WithDeprecatedTrait is deprecated in %s on line %d +Got: example + +Deprecated: Method DemoClass::printVal() is deprecated in %s on line %d +Value is: example +string(7) "example" + +Deprecated: Method DemoClass::$hooked::set() is deprecated in %s on line %d + +Deprecated: Method DemoClass::$hooked::get() is deprecated in %s on line %d +string(3) "foo" + +Deprecated: Constant DemoClass::CLASS_CONST is deprecated in %s on line %d +string(3) "FOO" + +Deprecated: Function demoFn() is deprecated in %s on line %d +demoFn + +Deprecated: Constant GLOBAL_CONST is deprecated in %s on line %d +string(3) "BAR" diff --git a/Zend/tests/attributes/delayed_target_validation/with_NoDiscard.phpt b/Zend/tests/attributes/delayed_target_validation/with_NoDiscard.phpt new file mode 100644 index 0000000000000..f2571ec07c2f1 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_NoDiscard.phpt @@ -0,0 +1,80 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\NoDiscard]: valid targets complain about discarding +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[NoDiscard] // Does nothing here + set => $value; + } + + #[DelayedTargetValidation] + #[NoDiscard] // Does nothing here + public const CLASS_CONST = 'FOO'; + + public function __construct( + #[DelayedTargetValidation] + #[NoDiscard] // Does nothing here + $str + ) { + echo "Got: $str\n"; + $this->val = $str; + } + + #[DelayedTargetValidation] + #[NoDiscard] // Does something here + public function printVal() { + echo 'Value is: ' . $this->val . "\n"; + return 123; + } +} + +#[DelayedTargetValidation] +#[NoDiscard] // Does something here +function demoFn() { + echo __FUNCTION__ . "\n"; + return 456; +} + +#[DelayedTargetValidation] +#[NoDiscard] // Does nothing here +const GLOBAL_CONST = 'BAR'; + +$d = new DemoClass('example'); +$d->printVal(); +$v = $d->printVal(); +var_dump($d->val); +$d->hooked = "foo"; +var_dump($d->hooked); +// NoDiscard does not support property hooks, this should not complain +$d->hooked; +var_dump(DemoClass::CLASS_CONST); +demoFn(); +$v = demoFn(); +var_dump(GLOBAL_CONST); +?> +--EXPECTF-- +Got: example + +Warning: The return value of method DemoClass::printVal() should either be used or intentionally ignored by casting it as (void) in %s on line %d +Value is: example +Value is: example +string(7) "example" +string(3) "foo" +string(3) "FOO" + +Warning: The return value of function demoFn() should either be used or intentionally ignored by casting it as (void) in %s on line %d +demoFn +demoFn +string(3) "BAR" diff --git a/Zend/tests/attributes/delayed_target_validation/with_Override_error_get.phpt b/Zend/tests/attributes/delayed_target_validation/with_Override_error_get.phpt new file mode 100644 index 0000000000000..a33e83d517a30 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_Override_error_get.phpt @@ -0,0 +1,18 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Override]: non-overrides still error (get hook) +--FILE-- + $this->hooked; + set => $value; + } +} + +?> +--EXPECTF-- +Fatal error: DemoClass::$hooked::get() has #[\Override] attribute, but no matching parent method exists in %s on line %d diff --git a/Zend/tests/attributes/delayed_target_validation/with_Override_error_method.phpt b/Zend/tests/attributes/delayed_target_validation/with_Override_error_method.phpt new file mode 100644 index 0000000000000..ecca1daff0fd3 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_Override_error_method.phpt @@ -0,0 +1,18 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Override]: non-overrides still error (method) +--FILE-- +val . "\n"; + return 123; + } +} + +?> +--EXPECTF-- +Fatal error: DemoClass::printVal() has #[\Override] attribute, but no matching parent method exists in %s on line %d diff --git a/Zend/tests/attributes/delayed_target_validation/with_Override_error_prop.phpt b/Zend/tests/attributes/delayed_target_validation/with_Override_error_prop.phpt new file mode 100644 index 0000000000000..3a44fa9b22cda --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_Override_error_prop.phpt @@ -0,0 +1,15 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Override]: non-overrides still error (normal property) +--FILE-- + +--EXPECTF-- +Fatal error: DemoClass::$prop has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/delayed_target_validation/with_Override_error_set.phpt b/Zend/tests/attributes/delayed_target_validation/with_Override_error_set.phpt new file mode 100644 index 0000000000000..d99580646c548 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_Override_error_set.phpt @@ -0,0 +1,18 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Override]: non-overrides still error (set hook) +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[Override] // Does something here + set => $value; + } +} + +?> +--EXPECTF-- +Fatal error: DemoClass::$hooked::set() has #[\Override] attribute, but no matching parent method exists in %s on line %d diff --git a/Zend/tests/attributes/delayed_target_validation/with_Override_okay.phpt b/Zend/tests/attributes/delayed_target_validation/with_Override_okay.phpt new file mode 100644 index 0000000000000..dd077f4b9cbd3 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_Override_okay.phpt @@ -0,0 +1,84 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\Override]: invalid targets or actual overrides don't do anything +--FILE-- + $this->hooked; + set => $value; + } + + public function printVal() { + echo __METHOD__ . "\n"; + } +} + +#[DelayedTargetValidation] +#[Override] // Does nothing here +class DemoClass extends Base { + #[DelayedTargetValidation] + #[Override] // Does something here + public $val; + + public string $hooked { + #[DelayedTargetValidation] + #[Override] // Does something here + get => $this->hooked; + #[DelayedTargetValidation] + #[Override] // Does something here + set => $value; + } + + #[DelayedTargetValidation] + #[Override] // Does nothing here + public const CLASS_CONST = 'FOO'; + + public function __construct( + #[DelayedTargetValidation] + #[Override] // Does nothing here + $str + ) { + echo "Got: $str\n"; + $this->val = $str; + } + + #[DelayedTargetValidation] + #[Override] // Does something here + public function printVal() { + echo 'Value is: ' . $this->val . "\n"; + return 123; + } +} + +#[DelayedTargetValidation] +#[Override] // Does nothing here +function demoFn() { + echo __FUNCTION__ . "\n"; + return 456; +} + +#[DelayedTargetValidation] +#[Override] // Does nothing here +const GLOBAL_CONST = 'BAR'; + +$d = new DemoClass('example'); +$d->printVal(); +var_dump($d->val); +$d->hooked = "foo"; +var_dump($d->hooked); +var_dump(DemoClass::CLASS_CONST); +demoFn(); +var_dump(GLOBAL_CONST); +?> +--EXPECT-- +Got: example +Value is: example +string(7) "example" +string(3) "foo" +string(3) "FOO" +demoFn +string(3) "BAR" diff --git a/Zend/tests/attributes/delayed_target_validation/with_ReturnTypeWillChange.phpt b/Zend/tests/attributes/delayed_target_validation/with_ReturnTypeWillChange.phpt new file mode 100644 index 0000000000000..c562075cd6c05 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_ReturnTypeWillChange.phpt @@ -0,0 +1,82 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\ReturnTypeWillChange]: valid targets suppress return type warnings +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[ReturnTypeWillChange] // Does nothing here + set => $value; + } + + #[DelayedTargetValidation] + #[ReturnTypeWillChange] // Does nothing here + public const CLASS_CONST = 'FOO'; + + public function __construct( + #[DelayedTargetValidation] + #[ReturnTypeWillChange] // Does nothing here + $str + ) { + echo "Got: $str\n"; + $this->val = $str; + } + + #[DelayedTargetValidation] + #[ReturnTypeWillChange] // Does something here + public function printVal() { + echo 'Value is: ' . $this->val . "\n"; + } + + #[DelayedTargetValidation] + #[ReturnTypeWillChange] // Does something here + public function count() { + return 5; + } +} + +#[DelayedTargetValidation] +#[ReturnTypeWillChange] // Does nothing here +function demoFn() { + echo __FUNCTION__ . "\n"; + return 456; +} + +#[DelayedTargetValidation] +#[ReturnTypeWillChange] // Does nothing here +const GLOBAL_CONST = 'BAR'; + +$d = new DemoClass('example'); +$d->printVal(); +var_dump($d->val); +$d->hooked = "foo"; +var_dump($d->hooked); +var_dump(DemoClass::CLASS_CONST); +demoFn(); +var_dump(GLOBAL_CONST); +?> +--EXPECTF-- +Deprecated: Return type of WithoutAttrib::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in %s on line %d +Got: example +Value is: example +string(7) "example" +string(3) "foo" +string(3) "FOO" +demoFn +string(3) "BAR" diff --git a/Zend/tests/attributes/delayed_target_validation/with_SensitiveParameter.phpt b/Zend/tests/attributes/delayed_target_validation/with_SensitiveParameter.phpt new file mode 100644 index 0000000000000..270c031f6bbf0 --- /dev/null +++ b/Zend/tests/attributes/delayed_target_validation/with_SensitiveParameter.phpt @@ -0,0 +1,82 @@ +--TEST-- +#[\DelayedTargetValidation] with #[\SensitiveParameter]: parameter still redacted +--FILE-- + $this->hooked; + #[DelayedTargetValidation] + #[SensitiveParameter] // Does nothing here + set => $value; + } + + #[DelayedTargetValidation] + #[SensitiveParameter] // Does nothing here + public const CLASS_CONST = 'FOO'; + + public function __construct( + #[DelayedTargetValidation] + #[SensitiveParameter] // Does something here + $str + ) { + echo "Got: $str\n"; + $this->val = $str; + } + + #[DelayedTargetValidation] + #[SensitiveParameter] // Does nothing here + public function printVal( + #[DelayedTargetValidation] + #[SensitiveParameter] + $sensitive // Does something here + ) { + throw new Exception('Testing backtrace'); + } + +} + +#[DelayedTargetValidation] +#[SensitiveParameter] // Does nothing here +function demoFn() { + echo __FUNCTION__ . "\n"; + return 456; +} + +#[DelayedTargetValidation] +#[SensitiveParameter] // Does nothing here +const GLOBAL_CONST = 'BAR'; + +$d = new DemoClass('example'); +var_dump($d->val); +$d->hooked = "foo"; +var_dump($d->hooked); +var_dump(DemoClass::CLASS_CONST); +demoFn(); +var_dump(GLOBAL_CONST); + +$d->printVal('BAZ'); + + +?> +--EXPECTF-- +Got: example +string(7) "example" +string(3) "foo" +string(3) "FOO" +demoFn +string(3) "BAR" + +Fatal error: Uncaught Exception: Testing backtrace in %s:%d +Stack trace: +#0 %s(%d): DemoClass->printVal(Object(SensitiveParameterValue)) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/deprecated/error_on_class.phpt b/Zend/tests/attributes/deprecated/error_on_class.phpt new file mode 100644 index 0000000000000..97c48af1491f9 --- /dev/null +++ b/Zend/tests/attributes/deprecated/error_on_class.phpt @@ -0,0 +1,11 @@ +--TEST-- +#[\Deprecated]: Using on a class +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply #[\Deprecated] to class Demo in %s on line %d diff --git a/Zend/tests/attributes/deprecated/error_on_enum.phpt b/Zend/tests/attributes/deprecated/error_on_enum.phpt new file mode 100644 index 0000000000000..0d998a2389923 --- /dev/null +++ b/Zend/tests/attributes/deprecated/error_on_enum.phpt @@ -0,0 +1,11 @@ +--TEST-- +#[\Deprecated]: Using on an enum +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply #[\Deprecated] to enum Demo in %s on line %d diff --git a/Zend/tests/attributes/deprecated/error_on_interface.phpt b/Zend/tests/attributes/deprecated/error_on_interface.phpt new file mode 100644 index 0000000000000..595181a7cecd5 --- /dev/null +++ b/Zend/tests/attributes/deprecated/error_on_interface.phpt @@ -0,0 +1,11 @@ +--TEST-- +#[\Deprecated]: Using on an interface +--FILE-- + +--EXPECTF-- +Fatal error: Cannot apply #[\Deprecated] to interface Demo in %s on line %d diff --git a/Zend/tests/attributes/deprecated/traits/basic.phpt b/Zend/tests/attributes/deprecated/traits/basic.phpt new file mode 100644 index 0000000000000..77738058e2a56 --- /dev/null +++ b/Zend/tests/attributes/deprecated/traits/basic.phpt @@ -0,0 +1,33 @@ +--TEST-- +#[\Deprecated]: Basic trait deprecation +--FILE-- + +--EXPECTF-- +Deprecated: Trait DemoTrait1 used by DemoClass is deprecated, please do not use in %s on line %d + +Deprecated: Trait DemoTrait2 used by DemoClass is deprecated since 2.7, will be removed in 3.0 in %s on line %d + +Deprecated: Trait DemoTrait3 used by DemoClass is deprecated, going away in %s on line %d + +Deprecated: Trait DemoTrait4 used by DemoClass is deprecated since 3.5 in %s on line %d diff --git a/Zend/tests/attributes/deprecated/traits/inheritance.phpt b/Zend/tests/attributes/deprecated/traits/inheritance.phpt new file mode 100644 index 0000000000000..6a54a83e2e440 --- /dev/null +++ b/Zend/tests/attributes/deprecated/traits/inheritance.phpt @@ -0,0 +1,18 @@ +--TEST-- +#[\Deprecated]: Deprecated traits only apply to direct use, not inheritance +--FILE-- + +--EXPECTF-- +Deprecated: Trait DemoTrait used by DemoClass is deprecated in %s on line %d diff --git a/Zend/tests/attributes/deprecated/traits/insteadof_unused_warnings.phpt b/Zend/tests/attributes/deprecated/traits/insteadof_unused_warnings.phpt new file mode 100644 index 0000000000000..390455f73ba73 --- /dev/null +++ b/Zend/tests/attributes/deprecated/traits/insteadof_unused_warnings.phpt @@ -0,0 +1,43 @@ +--TEST-- +#[\Deprecated]: `insteadof` rendering a trait unused still triggers deprecation messages +--FILE-- +lowerCase()); +var_dump($d->upperCase()); + +?> +--EXPECTF-- +Deprecated: Trait DemoTraitA used by DemoClass is deprecated in %s on line %d + +Deprecated: Trait DemoTraitB used by DemoClass is deprecated in %s on line %d +string(1) "a" +string(1) "A" diff --git a/Zend/tests/attributes/deprecated/traits/multiple_traits.phpt b/Zend/tests/attributes/deprecated/traits/multiple_traits.phpt new file mode 100644 index 0000000000000..2d838493f4511 --- /dev/null +++ b/Zend/tests/attributes/deprecated/traits/multiple_traits.phpt @@ -0,0 +1,22 @@ +--TEST-- +#[\Deprecated]: Using multiple traits +--FILE-- + +--EXPECTF-- +Deprecated: Trait DemoTraitA used by DemoClass is deprecated in %s on line %d + +Deprecated: Trait DemoTraitB used by DemoClass is deprecated in %s on line %d diff --git a/Zend/tests/attributes/deprecated/traits/throwing_error_handler.phpt b/Zend/tests/attributes/deprecated/traits/throwing_error_handler.phpt new file mode 100644 index 0000000000000..2704ea68e5b3a --- /dev/null +++ b/Zend/tests/attributes/deprecated/traits/throwing_error_handler.phpt @@ -0,0 +1,25 @@ +--TEST-- +#[\Deprecated]: Deprecation converted to ErrorException does not break +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught ErrorException: Trait DemoTrait used by DemoClass is deprecated in %s:%d +Stack trace: +#0 %s: my_error_handler(16384, 'Trait DemoTrait...', '%s', %d) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/attributes/deprecated/traits/trait_using_trait.phpt b/Zend/tests/attributes/deprecated/traits/trait_using_trait.phpt new file mode 100644 index 0000000000000..851adeb232d30 --- /dev/null +++ b/Zend/tests/attributes/deprecated/traits/trait_using_trait.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Deprecated]: Trait using a deprecated trait +--FILE-- + +--EXPECTF-- +Deprecated: Trait DemoTraitA used by DemoTraitB is deprecated in %s on line %d diff --git a/Zend/tests/attributes/deprecated/traits/with_conflicts.phpt b/Zend/tests/attributes/deprecated/traits/with_conflicts.phpt new file mode 100644 index 0000000000000..5adbb3c57d494 --- /dev/null +++ b/Zend/tests/attributes/deprecated/traits/with_conflicts.phpt @@ -0,0 +1,43 @@ +--TEST-- +#[\Deprecated]: Using multiple traits with conflict resolution +--FILE-- +lowerCase()); +var_dump($d->upperCase()); + +?> +--EXPECTF-- +Deprecated: Trait DemoTraitA used by DemoClass is deprecated in %s on line %d + +Deprecated: Trait DemoTraitB used by DemoClass is deprecated in %s on line %d +string(1) "a" +string(1) "B" diff --git a/Zend/tests/attributes/override/properties_01.phpt b/Zend/tests/attributes/override/properties_01.phpt new file mode 100644 index 0000000000000..d83f935f83496 --- /dev/null +++ b/Zend/tests/attributes/override/properties_01.phpt @@ -0,0 +1,39 @@ +--TEST-- +#[\Override]: Properties +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_02.phpt b/Zend/tests/attributes/override/properties_02.phpt new file mode 100644 index 0000000000000..aefe84f150db1 --- /dev/null +++ b/Zend/tests/attributes/override/properties_02.phpt @@ -0,0 +1,15 @@ +--TEST-- +#[\Override]: Properties: No parent class. +--FILE-- + +--EXPECTF-- +Fatal error: C::$c has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_03.phpt b/Zend/tests/attributes/override/properties_03.phpt new file mode 100644 index 0000000000000..c2b2ea0acc2e0 --- /dev/null +++ b/Zend/tests/attributes/override/properties_03.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\Override]: Properties: No parent class, but child implements matching interface. +--FILE-- + +--EXPECTF-- +Fatal error: P::$i has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_04.phpt b/Zend/tests/attributes/override/properties_04.phpt new file mode 100644 index 0000000000000..142a1d0c640ac --- /dev/null +++ b/Zend/tests/attributes/override/properties_04.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\Override]: Properties: No parent class, but child implements matching interface (2). +--FILE-- + +--EXPECTF-- +Fatal error: P::$i has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_05.phpt b/Zend/tests/attributes/override/properties_05.phpt new file mode 100644 index 0000000000000..71113dad60e43 --- /dev/null +++ b/Zend/tests/attributes/override/properties_05.phpt @@ -0,0 +1,26 @@ +--TEST-- +#[\Override]: Properties: No parent interface. +--FILE-- + +--EXPECTF-- +Fatal error: I::$i has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_06.phpt b/Zend/tests/attributes/override/properties_06.phpt new file mode 100644 index 0000000000000..66309ac625c0c --- /dev/null +++ b/Zend/tests/attributes/override/properties_06.phpt @@ -0,0 +1,15 @@ +--TEST-- +#[\Override]: Properties: On trait. +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_07.phpt b/Zend/tests/attributes/override/properties_07.phpt new file mode 100644 index 0000000000000..ae9ed4b8dbf71 --- /dev/null +++ b/Zend/tests/attributes/override/properties_07.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Override]: Properties: On used trait without parent property. +--FILE-- + +--EXPECTF-- +Fatal error: Foo::$t has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_08.phpt b/Zend/tests/attributes/override/properties_08.phpt new file mode 100644 index 0000000000000..c976dcecdc149 --- /dev/null +++ b/Zend/tests/attributes/override/properties_08.phpt @@ -0,0 +1,23 @@ +--TEST-- +#[\Override]: Properties: On used trait with interface property. +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_09.phpt b/Zend/tests/attributes/override/properties_09.phpt new file mode 100644 index 0000000000000..85970ba11a42a --- /dev/null +++ b/Zend/tests/attributes/override/properties_09.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Override]: Properties: Parent property is private, child property is public. +--FILE-- + +--EXPECTF-- +Fatal error: C::$p has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_10.phpt b/Zend/tests/attributes/override/properties_10.phpt new file mode 100644 index 0000000000000..ce1d7f46fd574 --- /dev/null +++ b/Zend/tests/attributes/override/properties_10.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Override]: Properties: Parent property is private, child property is private. +--FILE-- + +--EXPECTF-- +Fatal error: C::$p has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_11.phpt b/Zend/tests/attributes/override/properties_11.phpt new file mode 100644 index 0000000000000..354e718505d19 --- /dev/null +++ b/Zend/tests/attributes/override/properties_11.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Override]: Properties: Parent property is protected, child property is public. +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_12.phpt b/Zend/tests/attributes/override/properties_12.phpt new file mode 100644 index 0000000000000..351ed26b0af84 --- /dev/null +++ b/Zend/tests/attributes/override/properties_12.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Override]: Properties: Parent property is protected, child property is protected. +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_13.phpt b/Zend/tests/attributes/override/properties_13.phpt new file mode 100644 index 0000000000000..d9ab0a6b9a299 --- /dev/null +++ b/Zend/tests/attributes/override/properties_13.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\Override]: Properties: Redeclared trait property. +--FILE-- + +--EXPECTF-- +Fatal error: C::$t has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_14.phpt b/Zend/tests/attributes/override/properties_14.phpt new file mode 100644 index 0000000000000..4e098c6d7212c --- /dev/null +++ b/Zend/tests/attributes/override/properties_14.phpt @@ -0,0 +1,25 @@ +--TEST-- +#[\Override]: Properties: Redeclared trait property with interface. +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_15.phpt b/Zend/tests/attributes/override/properties_15.phpt new file mode 100644 index 0000000000000..37d46b2a170a3 --- /dev/null +++ b/Zend/tests/attributes/override/properties_15.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Override]: Properties: Valid anonymous class. +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_16.phpt b/Zend/tests/attributes/override/properties_16.phpt new file mode 100644 index 0000000000000..57ea17818c406 --- /dev/null +++ b/Zend/tests/attributes/override/properties_16.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\Override]: Properties: Invalid anonymous class. +--FILE-- + +--EXPECTF-- +Fatal error: I@anonymous::$c has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_17.phpt b/Zend/tests/attributes/override/properties_17.phpt new file mode 100644 index 0000000000000..389d66035ea44 --- /dev/null +++ b/Zend/tests/attributes/override/properties_17.phpt @@ -0,0 +1,16 @@ +--TEST-- +#[\Override]: Properties: Static property no parent class. +--FILE-- + +--EXPECTF-- +Fatal error: C::$c has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/attributes/override/properties_18.phpt b/Zend/tests/attributes/override/properties_18.phpt new file mode 100644 index 0000000000000..66731a69f8e8a --- /dev/null +++ b/Zend/tests/attributes/override/properties_18.phpt @@ -0,0 +1,19 @@ +--TEST-- +#[\Override]: Properties: Static property. +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_19.phpt b/Zend/tests/attributes/override/properties_19.phpt new file mode 100644 index 0000000000000..1844664e3ca27 --- /dev/null +++ b/Zend/tests/attributes/override/properties_19.phpt @@ -0,0 +1,21 @@ +--TEST-- +#[\Override]: Properties: valid promoted property +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/attributes/override/properties_20.phpt b/Zend/tests/attributes/override/properties_20.phpt new file mode 100644 index 0000000000000..fcfbfa727c849 --- /dev/null +++ b/Zend/tests/attributes/override/properties_20.phpt @@ -0,0 +1,17 @@ +--TEST-- +#[\Override]: Properties: invalid promoted property +--FILE-- + +--EXPECTF-- +Fatal error: C::$c has #[\Override] attribute, but no matching parent property exists in %s on line %d diff --git a/Zend/tests/bug29890.phpt b/Zend/tests/bug29890.phpt index 6f1e874882e62..27cb1b311ea94 100644 --- a/Zend/tests/bug29890.phpt +++ b/Zend/tests/bug29890.phpt @@ -20,4 +20,4 @@ define("TEST",3); ?> --EXPECT-- -error :Constant TEST already defined +error :Constant TEST already defined, this will be an error in PHP 9 diff --git a/Zend/tests/bug34617.phpt b/Zend/tests/bug34617.phpt index a6f3ea8ca7f07..736f31d032e56 100644 --- a/Zend/tests/bug34617.phpt +++ b/Zend/tests/bug34617.phpt @@ -11,7 +11,6 @@ function boom() $thing = new Thing(); xml_set_object($reader, $thing); die("ok\n"); - xml_parser_free($reader); } boom(); ?> diff --git a/Zend/tests/bug40236.phpt b/Zend/tests/bug40236.phpt index 7ed298c1eed66..5fb3fddc573db 100644 --- a/Zend/tests/bug40236.phpt +++ b/Zend/tests/bug40236.phpt @@ -8,7 +8,7 @@ if (extension_loaded("readline")) die("skip Test doesn't support readline"); --EXPECT-- Interactive shell (-a) requires the readline extension. diff --git a/Zend/tests/bug40770.phpt b/Zend/tests/bug40770.phpt index f37d96d5ff333..bdbae4cf8f1a2 100644 --- a/Zend/tests/bug40770.phpt +++ b/Zend/tests/bug40770.phpt @@ -4,6 +4,9 @@ Bug #40770 (Apache child exits when PHP memory limit reached) memory_limit=8M --SKIPIF-- ---EXPECTF-- -Warning: feof(): wrapper::stream_eof is not implemented! Assuming EOF in %s on line %d +try { + feof($fp); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} -Fatal error: Uncaught Exception in %s:%d -Stack trace: -#0 [internal function]: wrapper->stream_eof() -#1 %s(%d): feof(Resource id #%d) -#2 {main} - thrown in %s on line %d +?> +--EXPECT-- +Exception: cannot eof diff --git a/Zend/tests/bug55509.phpt b/Zend/tests/bug55509.phpt index b45150a4979ef..942df09bc0f91 100644 --- a/Zend/tests/bug55509.phpt +++ b/Zend/tests/bug55509.phpt @@ -28,7 +28,7 @@ if (PHP_OS == 'Linux') { } } elseif (PHP_OS == 'FreeBSD') { - $lines = explode("\n",`sysctl -a`); + $lines = explode("\n", shell_exec("sysctl -a")); $infos = array(); foreach ($lines as $line) { if (!$line){ diff --git a/Zend/tests/bug64677.phpt b/Zend/tests/bug64677.phpt index c3b168bd83b51..4995602e00124 100644 --- a/Zend/tests/bug64677.phpt +++ b/Zend/tests/bug64677.phpt @@ -17,5 +17,12 @@ function show_outputa($prepend, $output) { show_outputa('Files: ', `cd .`); // this works as expected ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The backtick (`) operator is deprecated, use shell_exec() instead in %s on line %d + +Deprecated: The backtick (`) operator is deprecated, use shell_exec() instead in %s on line %d + +Deprecated: The backtick (`) operator is deprecated, use shell_exec() instead in %s on line %d + +Deprecated: The backtick (`) operator is deprecated, use shell_exec() instead in %s on line %d Okey diff --git a/Zend/tests/bug67368.phpt b/Zend/tests/bug67368.phpt index f588270f5984c..50ca00d36d406 100644 --- a/Zend/tests/bug67368.phpt +++ b/Zend/tests/bug67368.phpt @@ -1,7 +1,5 @@ --TEST-- Bug #67368 (Memory leak with immediately dereferenced array in class constant) ---INI-- -report_memleaks=1 --FILE-- --EXPECTF-- -Warning: Cannot unbind $this of method in %s on line %d +Warning: Cannot unbind $this of method, this will be an error in PHP 9 in %s on line %d int(3) diff --git a/Zend/tests/bug71300.phpt b/Zend/tests/bug71300.phpt index 40734b054933b..abf9ebc5307cd 100644 --- a/Zend/tests/bug71300.phpt +++ b/Zend/tests/bug71300.phpt @@ -22,7 +22,22 @@ function test2() { var_dump(test2()); ?> --EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(4) "test" +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + Warning: Array to string conversion in %s on line %d string(9) "Arraytest" diff --git a/Zend/tests/bug72543_2.phpt b/Zend/tests/bug72543_2.phpt index 2070d65bddc9f..fb96cc55449dd 100644 --- a/Zend/tests/bug72543_2.phpt +++ b/Zend/tests/bug72543_2.phpt @@ -9,7 +9,8 @@ unset($ref); $arr[0][$arr[0]] = null; var_dump($arr); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d array(1) { [0]=> array(1) { diff --git a/Zend/tests/bug77494.phpt b/Zend/tests/bug77494.phpt deleted file mode 100644 index 7f808c2c0f52a..0000000000000 --- a/Zend/tests/bug77494.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Bug #77494 (Disabling class causes segfault on member access) ---EXTENSIONS-- -curl ---INI-- -disable_classes=CURLFile,ErrorException ---FILE-- -name); -$b = new ErrorException(); -var_dump($b->message); -?> ---EXPECTF-- -Warning: CURLFile() has been disabled for security reasons in %sbug77494.php on line 2 - -Warning: Undefined property: CURLFile::$name in %s on line %d -NULL - -Warning: ErrorException() has been disabled for security reasons in %s on line %d - -Warning: Undefined property: ErrorException::$message in %s on line %d -NULL diff --git a/Zend/tests/bug79668.phpt b/Zend/tests/bug79668.phpt deleted file mode 100644 index 5e73a7469b6ff..0000000000000 --- a/Zend/tests/bug79668.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Bug #79668 (get_defined_functions(true) may miss functions) ---INI-- -disable_functions=sha1_file,password_hash ---FILE-- - ---EXPECT-- -bool(true) -bool(false) -bool(true) -bool(false) diff --git a/Zend/tests/bug81104.phpt b/Zend/tests/bug81104.phpt index 8e7d7e7d7381e..12c137170fe4c 100644 --- a/Zend/tests/bug81104.phpt +++ b/Zend/tests/bug81104.phpt @@ -2,7 +2,6 @@ Bug #81104: Warning: "Failed to set memory limit to ... bytes" emitted after exit in debug --INI-- memory_limit=5M -report_memleaks=0 --FILE-- getMessage(), PHP_EOL; } +try { + assert(false && $y = clone($x, )); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone($x, [ "foo" => $foo, "bar" => $bar ])); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone($x, $array)); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone($x, $array, $extraParameter, $trailingComma, )); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone(object: $x, withProperties: [ "foo" => $foo, "bar" => $bar ])); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone($x, withProperties: [ "foo" => $foo, "bar" => $bar ])); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone(object: $x)); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone(object: $x, [ "foo" => $foo, "bar" => $bar ])); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + assert(false && $y = clone(...["object" => $x, "withProperties" => [ "foo" => $foo, "bar" => $bar ]])); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + try { assert(false && $y = clone(...)); } catch (Error $e) { @@ -28,4 +82,13 @@ try { --EXPECT-- assert(false && ($y = \clone($x))) assert(false && ($y = \clone($x))) +assert(false && ($y = \clone($x))) +assert(false && ($y = \clone($x, ['foo' => $foo, 'bar' => $bar]))) +assert(false && ($y = \clone($x, $array))) +assert(false && ($y = \clone($x, $array, $extraParameter, $trailingComma))) +assert(false && ($y = \clone(object: $x, withProperties: ['foo' => $foo, 'bar' => $bar]))) +assert(false && ($y = \clone($x, withProperties: ['foo' => $foo, 'bar' => $bar]))) +assert(false && ($y = \clone(object: $x))) +assert(false && ($y = \clone(object: $x, ['foo' => $foo, 'bar' => $bar]))) +assert(false && ($y = \clone(...['object' => $x, 'withProperties' => ['foo' => $foo, 'bar' => $bar]]))) assert(false && ($y = \clone(...))) diff --git a/Zend/tests/clone/clone_with_001.phpt b/Zend/tests/clone/clone_with_001.phpt new file mode 100644 index 0000000000000..3623706a980c8 --- /dev/null +++ b/Zend/tests/clone/clone_with_001.phpt @@ -0,0 +1,71 @@ +--TEST-- +Clone with basic +--FILE-- + 'BAZ', + 'array' => [1, 2, 3], +]; + +var_dump(clone $x); +var_dump(clone($x)); +var_dump(clone($x, [ 'foo' => $foo, 'bar' => $bar ])); +var_dump(clone($x, $array)); +var_dump(clone($x, [ 'obj' => $x ])); + +var_dump(clone($x, [ + 'abc', + 'def', + new Dummy(), + 'named' => 'value', +])); + +?> +--EXPECTF-- +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} +object(stdClass)#%d (2) { + ["foo"]=> + string(3) "FOO" + ["bar"]=> + object(Dummy)#%d (0) { + } +} +object(stdClass)#%d (2) { + ["baz"]=> + string(3) "BAZ" + ["array"]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +object(stdClass)#%d (1) { + ["obj"]=> + object(stdClass)#%d (0) { + } +} +object(stdClass)#%d (4) { + ["0"]=> + string(3) "abc" + ["1"]=> + string(3) "def" + ["2"]=> + object(Dummy)#%d (0) { + } + ["named"]=> + string(5) "value" +} diff --git a/Zend/tests/clone/clone_with_002.phpt b/Zend/tests/clone/clone_with_002.phpt new file mode 100644 index 0000000000000..8b86e64c76aa8 --- /dev/null +++ b/Zend/tests/clone/clone_with_002.phpt @@ -0,0 +1,114 @@ +--TEST-- +Clone with respects visiblity +--FILE-- + 'updated A', 'b' => 'updated B', 'c' => 'updated C', 'd' => 'updated D' ]); + } +} + +class C extends P { + public function m2() { + return clone($this, [ 'a' => 'updated A', 'b' => 'updated B', 'c' => 'dynamic C' ]); + } + + public function m3() { + return clone($this, [ 'd' => 'inaccessible' ]); + } +} + +class Unrelated { + public function m3(P $p) { + return clone($p, [ 'b' => 'inaccessible' ]); + } +} + +$p = new P(); + +var_dump(clone($p, [ 'a' => 'updated A' ])); +var_dump($p->m1()); + +$c = new C(); +var_dump($c->m1()); +var_dump($c->m2()); +try { + var_dump($c->m3()); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump(clone($p, [ 'b' => 'inaccessible' ])); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump(clone($p, [ 'd' => 'inaccessible' ])); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump((new Unrelated())->m3($p)); +} catch (Error $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +object(P)#%d (4) { + ["a"]=> + string(9) "updated A" + ["b":protected]=> + string(7) "default" + ["c":"P":private]=> + string(7) "default" + ["d"]=> + string(7) "default" +} +object(P)#%d (4) { + ["a"]=> + string(9) "updated A" + ["b":protected]=> + string(9) "updated B" + ["c":"P":private]=> + string(9) "updated C" + ["d"]=> + string(9) "updated D" +} +object(C)#%d (4) { + ["a"]=> + string(9) "updated A" + ["b":protected]=> + string(9) "updated B" + ["c":"P":private]=> + string(9) "updated C" + ["d"]=> + string(9) "updated D" +} + +Deprecated: Creation of dynamic property C::$c is deprecated in %s on line %d +object(C)#%d (5) { + ["a"]=> + string(9) "updated A" + ["b":protected]=> + string(9) "updated B" + ["c":"P":private]=> + string(7) "default" + ["d"]=> + string(7) "default" + ["c"]=> + string(9) "dynamic C" +} +Error: Cannot modify private(set) property P::$d from scope C +Error: Cannot access protected property P::$b +Error: Cannot modify private(set) property P::$d from global scope +Error: Cannot access protected property P::$b diff --git a/Zend/tests/clone/clone_with_003.phpt b/Zend/tests/clone/clone_with_003.phpt new file mode 100644 index 0000000000000..48fb2b1f6a3d6 --- /dev/null +++ b/Zend/tests/clone/clone_with_003.phpt @@ -0,0 +1,23 @@ +--TEST-- +Clone with supports property hooks +--FILE-- +hooked = strtoupper($value); + } + } +} + +$c = new Clazz(); + +var_dump(clone($c, [ 'hooked' => 'updated' ])); + +?> +--EXPECTF-- +object(Clazz)#%d (1) { + ["hooked"]=> + string(7) "UPDATED" +} diff --git a/Zend/tests/clone/clone_with_004.phpt b/Zend/tests/clone/clone_with_004.phpt new file mode 100644 index 0000000000000..e9985d62bd04b --- /dev/null +++ b/Zend/tests/clone/clone_with_004.phpt @@ -0,0 +1,82 @@ +--TEST-- +Clone with evaluation order +--FILE-- +hooked = strtoupper($value); + } + } + + public string $maxLength { + set { + echo __FUNCTION__, PHP_EOL; + + if (strlen($value) > 5) { + throw new \Exception('Length exceeded'); + } + + $this->maxLength = $value; + } + } + + public string $minLength { + set { + echo __FUNCTION__, PHP_EOL; + + if (strlen($value) < 5) { + throw new \Exception('Length unsufficient'); + } + + $this->minLength = $value; + } + } +} + +$c = new Clazz(); + +var_dump(clone($c, [ 'hooked' => 'updated' ])); +echo PHP_EOL; +var_dump(clone($c, [ 'hooked' => 'updated', 'maxLength' => 'abc', 'minLength' => 'abcdef' ])); +echo PHP_EOL; +var_dump(clone($c, [ 'minLength' => 'abcdef', 'hooked' => 'updated', 'maxLength' => 'abc' ])); + +?> +--EXPECTF-- +$hooked::set +object(Clazz)#%d (1) { + ["hooked"]=> + string(7) "UPDATED" + ["maxLength"]=> + uninitialized(string) + ["minLength"]=> + uninitialized(string) +} + +$hooked::set +$maxLength::set +$minLength::set +object(Clazz)#%d (3) { + ["hooked"]=> + string(7) "UPDATED" + ["maxLength"]=> + string(3) "abc" + ["minLength"]=> + string(6) "abcdef" +} + +$minLength::set +$hooked::set +$maxLength::set +object(Clazz)#%d (3) { + ["hooked"]=> + string(7) "UPDATED" + ["maxLength"]=> + string(3) "abc" + ["minLength"]=> + string(6) "abcdef" +} diff --git a/Zend/tests/clone/clone_with_005.phpt b/Zend/tests/clone/clone_with_005.phpt new file mode 100644 index 0000000000000..55ffb2423d7e3 --- /dev/null +++ b/Zend/tests/clone/clone_with_005.phpt @@ -0,0 +1,64 @@ +--TEST-- +Clone with error handling +--FILE-- +hooked = strtoupper($value); + } + } + + public string $maxLength { + set { + echo __FUNCTION__, PHP_EOL; + + if (strlen($value) > 5) { + throw new \Exception('Length exceeded'); + } + + $this->maxLength = $value; + } + } + + public string $minLength { + set { + echo __FUNCTION__, PHP_EOL; + + if (strlen($value) < 5) { + throw new \Exception('Length insufficient'); + } + + $this->minLength = $value; + } + } +} + +$c = new Clazz(); + +try { + var_dump(clone($c, [ 'hooked' => 'updated', 'maxLength' => 'abcdef', 'minLength' => 'abc' ])); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +echo PHP_EOL; + +try { + var_dump(clone($c, [ 'hooked' => 'updated', 'minLength' => 'abc', 'maxLength' => 'abcdef' ])); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +$hooked::set +$maxLength::set +Exception: Length exceeded + +$hooked::set +$minLength::set +Exception: Length insufficient diff --git a/Zend/tests/clone/clone_with_006.phpt b/Zend/tests/clone/clone_with_006.phpt new file mode 100644 index 0000000000000..7b0b8520b8a82 --- /dev/null +++ b/Zend/tests/clone/clone_with_006.phpt @@ -0,0 +1,16 @@ +--TEST-- +Clone with error cases +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: clone(): Argument #2 ($withProperties) must be of type array, int given diff --git a/Zend/tests/clone/clone_with_007.phpt b/Zend/tests/clone/clone_with_007.phpt new file mode 100644 index 0000000000000..08cefd7f8cbe3 --- /dev/null +++ b/Zend/tests/clone/clone_with_007.phpt @@ -0,0 +1,29 @@ +--TEST-- +Clone with supports __clone +--FILE-- +foo = 'foo updated in __clone'; + $this->bar = 'bar updated in __clone'; + } +} + +$c = new Clazz('foo', 'bar'); + +var_dump(clone($c, [ 'foo' => 'foo updated in clone-with' ])); + +?> +--EXPECTF-- +object(Clazz)#%d (2) { + ["foo"]=> + string(25) "foo updated in clone-with" + ["bar"]=> + string(22) "bar updated in __clone" +} diff --git a/Zend/tests/clone/clone_with_008.phpt b/Zend/tests/clone/clone_with_008.phpt new file mode 100644 index 0000000000000..aa2c639fb7f1c --- /dev/null +++ b/Zend/tests/clone/clone_with_008.phpt @@ -0,0 +1,40 @@ +--TEST-- +Clone with readonly +--FILE-- +b = '__clone'; + } +} + +$c = new Clazz('default', 'default'); + +var_dump(clone($c, [ 'a' => "with" ])); + +try { + var_dump(clone($c, [ 'b' => "with" ])); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +object(Clazz)#%d (2) { + ["a"]=> + string(4) "with" + ["b"]=> + string(7) "__clone" +} +object(Clazz)#%d (2) { + ["a"]=> + string(7) "default" + ["b"]=> + string(4) "with" +} diff --git a/Zend/tests/clone/clone_with_009.phpt b/Zend/tests/clone/clone_with_009.phpt new file mode 100644 index 0000000000000..c6a7d2d18b982 --- /dev/null +++ b/Zend/tests/clone/clone_with_009.phpt @@ -0,0 +1,72 @@ +--TEST-- +Clone with lazy objects +--FILE-- + 2 ]); + + var_dump($reflector->isUninitializedLazyObject($obj)); + var_dump($obj); + var_dump($reflector->isUninitializedLazyObject($clone)); + var_dump($clone); +} + +$reflector = new ReflectionClass(C::class); + +$obj = $reflector->newLazyGhost(function ($obj) { + var_dump("initializer"); + $obj->__construct(); +}); + +test('Ghost', $obj); + +$obj = $reflector->newLazyProxy(function ($obj) { + var_dump("initializer"); + return new C(); +}); + +test('Proxy', $obj); + +?> +--EXPECTF-- +# Ghost: +string(11) "initializer" +bool(false) +object(C)#%d (1) { + ["a"]=> + int(1) +} +bool(false) +object(C)#%d (1) { + ["a"]=> + int(2) +} +# Proxy: +string(11) "initializer" +bool(false) +lazy proxy object(C)#%d (1) { + ["instance"]=> + object(C)#%d (1) { + ["a"]=> + int(1) + } +} +bool(false) +lazy proxy object(C)#%d (1) { + ["instance"]=> + object(C)#%d (1) { + ["a"]=> + int(2) + } +} diff --git a/Zend/tests/clone/clone_with_010.phpt b/Zend/tests/clone/clone_with_010.phpt new file mode 100644 index 0000000000000..29ecf714fc498 --- /dev/null +++ b/Zend/tests/clone/clone_with_010.phpt @@ -0,0 +1,21 @@ +--TEST-- +Clone with native classes +--FILE-- + "something" ])); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +try { + var_dump(clone(new \Random\Engine\Xoshiro256StarStar(), [ 'with' => "something" ])); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Error: Trying to clone an uncloneable object of class Random\Engine\Secure +Error: Cannot create dynamic property Random\Engine\Xoshiro256StarStar::$with diff --git a/Zend/tests/clone/clone_with_011.phpt b/Zend/tests/clone/clone_with_011.phpt new file mode 100644 index 0000000000000..5f8e99bb65f2f --- /dev/null +++ b/Zend/tests/clone/clone_with_011.phpt @@ -0,0 +1,18 @@ +--TEST-- +Clone with name mangling +--FILE-- + 'updated'])); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Error: Cannot access property starting with "\0" diff --git a/Zend/tests/clone/clone_with_012.phpt b/Zend/tests/clone/clone_with_012.phpt new file mode 100644 index 0000000000000..e24f0adad7c40 --- /dev/null +++ b/Zend/tests/clone/clone_with_012.phpt @@ -0,0 +1,35 @@ +--TEST-- +Clone with property hook updating readonly property +--FILE-- +foo = $value; + $this->bar = 'bar updated in hook'; + } + } + + public public(set) readonly string $bar; +} + +$f = new Clazz(); + +var_dump(clone($f, ['foo' => 'foo updated in clone-with'])); + +try { + var_dump(clone($f, ['foo' => 'foo updated in clone-with', 'bar' => 'bar updated in clone-with'])); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +object(Clazz)#%d (2) { + ["foo"]=> + string(25) "foo updated in clone-with" + ["bar"]=> + string(19) "bar updated in hook" +} +Error: Cannot modify readonly property Clazz::$bar diff --git a/Zend/tests/clone/clone_with_013.phpt b/Zend/tests/clone/clone_with_013.phpt new file mode 100644 index 0000000000000..13f2463255851 --- /dev/null +++ b/Zend/tests/clone/clone_with_013.phpt @@ -0,0 +1,31 @@ +--TEST-- +Clone with references +--FILE-- + &$ref]; + +try { + var_dump(clone($x, $with)); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +unset($ref); + +try { + var_dump(clone($x, $with)); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +Error: Cannot assign by reference when cloning with updated properties +object(stdClass)#%d (1) { + ["x"]=> + string(9) "reference" +} diff --git a/Zend/tests/closures/bug70630.phpt b/Zend/tests/closures/bug70630.phpt index 0e9e5449758f9..c75920899652c 100644 --- a/Zend/tests/closures/bug70630.phpt +++ b/Zend/tests/closures/bug70630.phpt @@ -7,4 +7,4 @@ $x = (new ReflectionFunction("substr"))->getClosure(); $x->call(new a); ?> --EXPECTF-- -Warning: Cannot rebind scope of closure created from function in %s on line %d +Warning: Cannot rebind scope of closure created from function, this will be an error in PHP 9 in %s on line %d diff --git a/Zend/tests/closures/bug70685.phpt b/Zend/tests/closures/bug70685.phpt index 737b4469fdbe4..7cb6aa094de42 100644 --- a/Zend/tests/closures/bug70685.phpt +++ b/Zend/tests/closures/bug70685.phpt @@ -15,8 +15,8 @@ var_dump($c); ?> --EXPECTF-- -Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls in %s on line %d +Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls, this will be an error in PHP 9 in %s on line %d NULL -Warning: Cannot rebind scope of closure created from method in %s on line %d +Warning: Cannot rebind scope of closure created from method, this will be an error in PHP 9 in %s on line %d NULL diff --git a/Zend/tests/closures/closure_016.phpt b/Zend/tests/closures/closure_016.phpt index 0f87f20f435aa..33860189a57ea 100644 --- a/Zend/tests/closures/closure_016.phpt +++ b/Zend/tests/closures/closure_016.phpt @@ -42,9 +42,9 @@ Foo::__invoke bool(true) Foo::__invoke bool(true) -Closure::__invoke +{closure:foo():9} bool(true) -Closure::__invoke +{closure:foo():9} bool(true) Closure::__invoke bool(true) diff --git a/Zend/tests/closures/closure_040.phpt b/Zend/tests/closures/closure_040.phpt index 436c99939b1ee..b733bdbef0537 100644 --- a/Zend/tests/closures/closure_040.phpt +++ b/Zend/tests/closures/closure_040.phpt @@ -36,4 +36,4 @@ $cas->bindTo($a, 'A'); --EXPECTF-- Closure::bindTo(): Argument #2 ($newScope) must be of type object|string|null, array given -Warning: Cannot bind an instance to a static closure in %s on line %d +Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d diff --git a/Zend/tests/closures/closure_041.phpt b/Zend/tests/closures/closure_041.phpt index d709257484115..64afde4ea22b1 100644 --- a/Zend/tests/closures/closure_041.phpt +++ b/Zend/tests/closures/closure_041.phpt @@ -80,16 +80,16 @@ bound: no scoped to A: bool(true) bound: no -Warning: Cannot unbind $this of closure using $this in %s on line %d +Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d NULL After binding, with same-class instance for the bound ones -Warning: Cannot bind an instance to a static closure in %s on line %d +Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d scoped to A: bool(false) bound: A (should be scoped to dummy class) -Warning: Cannot bind an instance to a static closure in %s on line %d +Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d scoped to A: bool(true) bound: A After binding, with different instance for the bound ones diff --git a/Zend/tests/closures/closure_043.phpt b/Zend/tests/closures/closure_043.phpt index bfcd37b38e1f5..8f60bd272469f 100644 --- a/Zend/tests/closures/closure_043.phpt +++ b/Zend/tests/closures/closure_043.phpt @@ -56,9 +56,9 @@ bool(false) After binding, null scope, with instance -Warning: Cannot bind an instance to a static closure in %s on line %d +Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d -Warning: Cannot bind an instance to a static closure in %s on line %d +Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d After binding, with scope, no instance bool(true) bool(false) @@ -68,7 +68,7 @@ bool(false) After binding, with scope, with instance -Warning: Cannot bind an instance to a static closure in %s on line %d +Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d -Warning: Cannot bind an instance to a static closure in %s on line %d +Warning: Cannot bind an instance to a static closure, this will be an error in PHP 9 in %s on line %d Done. diff --git a/Zend/tests/closures/closure_044.phpt b/Zend/tests/closures/closure_044.phpt index 544ad8bee8445..624450c168815 100644 --- a/Zend/tests/closures/closure_044.phpt +++ b/Zend/tests/closures/closure_044.phpt @@ -52,7 +52,7 @@ bool(false) bool(false) -Warning: Cannot unbind $this of closure using $this in %s on line %d +Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d NULL After binding, null scope, with instance @@ -67,7 +67,7 @@ bool(true) bool(false) -Warning: Cannot unbind $this of closure using $this in %s on line %d +Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d NULL After binding, with scope, with instance diff --git a/Zend/tests/closures/closure_046.phpt b/Zend/tests/closures/closure_046.phpt index 9dbcba5ce5442..19dd69e2a6fd2 100644 --- a/Zend/tests/closures/closure_046.phpt +++ b/Zend/tests/closures/closure_046.phpt @@ -50,7 +50,7 @@ bool(false) bool(false) -Warning: Cannot unbind $this of closure using $this in %s on line %d +Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d NULL After binding, with same-class instance for the bound one diff --git a/Zend/tests/closures/closure_061.phpt b/Zend/tests/closures/closure_061.phpt index 240f22e036ef7..23ab2f87a1c5b 100644 --- a/Zend/tests/closures/closure_061.phpt +++ b/Zend/tests/closures/closure_061.phpt @@ -118,13 +118,13 @@ bindTo(new Cls, null): Success! bindTo(new Cls, Cls::class): -Cannot rebind scope of closure created from function +Cannot rebind scope of closure created from function, this will be an error in PHP 9 bindTo(null, Cls::class): -Cannot rebind scope of closure created from function +Cannot rebind scope of closure created from function, this will be an error in PHP 9 bindTo(null, stdClass::class): -Cannot bind closure to scope of internal class stdClass +Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9 bindTo(new stdClass, null): Success! @@ -139,13 +139,13 @@ bindTo(new Cls, null): Success! bindTo(new Cls, Cls::class): -Cannot rebind scope of closure created from function +Cannot rebind scope of closure created from function, this will be an error in PHP 9 bindTo(null, Cls::class): -Cannot rebind scope of closure created from function +Cannot rebind scope of closure created from function, this will be an error in PHP 9 bindTo(null, stdClass::class): -Cannot bind closure to scope of internal class stdClass +Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9 bindTo(new stdClass, null): Success! @@ -157,25 +157,25 @@ bindTo(null, Cls::class): Success! bindTo(new Cls, null): -Cannot bind an instance to a static closure +Cannot bind an instance to a static closure, this will be an error in PHP 9 bindTo(new Cls, Cls::class): -Cannot bind an instance to a static closure +Cannot bind an instance to a static closure, this will be an error in PHP 9 bindTo(null, null): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 bindTo(null, ClsChild::class): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 bindTo(null, ClsUnrelated::class): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 (new Cls)->method() ------------------- bindTo(null, Cls::class): -Cannot unbind $this of method +Cannot unbind $this of method, this will be an error in PHP 9 bindTo(new Cls, Cls::class): Success! @@ -184,16 +184,16 @@ bindTo(new ClsChild, Cls::class): Success! bindTo(new ClsUnrelated, Cls::class): -Cannot bind method Cls::method() to object of class ClsUnrelated +Cannot bind method Cls::method() to object of class ClsUnrelated, this will be an error in PHP 9 bindTo(new Cls, null): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 bindTo(new Cls, ClsUnrelated::class): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 bindTo(new Cls, ClsChild::class): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 (new SplDoublyLinkedList)->count() ---------------------------------- @@ -205,19 +205,19 @@ bindTo(new SplStack, SplDoublyLinkedList::class): Success! bindTo(new ClsUnrelated, SplDoublyLinkedList::class): -Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated +Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated, this will be an error in PHP 9 bindTo(null, null): -Cannot unbind $this of method +Cannot unbind $this of method, this will be an error in PHP 9 bindTo(null, SplDoublyLinkedList::class): -Cannot unbind $this of method +Cannot unbind $this of method, this will be an error in PHP 9 bindTo(new SplDoublyLinkedList, null): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 bindTo(new SplDoublyLinkedList, ClsUnrelated::class): -Cannot rebind scope of closure created from method +Cannot rebind scope of closure created from method, this will be an error in PHP 9 (function() {})() ----------------- @@ -235,7 +235,7 @@ bindTo(null, Cls::class): Success! bindTo(null, stdClass::class): -Cannot bind closure to scope of internal class stdClass +Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9 bindTo(new stdClass, null): Success! diff --git a/Zend/tests/closures/closure_062.phpt b/Zend/tests/closures/closure_062.phpt index b8c0a981be527..d3db7998eea16 100644 --- a/Zend/tests/closures/closure_062.phpt +++ b/Zend/tests/closures/closure_062.phpt @@ -48,7 +48,7 @@ Test::staticMethod(); --EXPECTF-- instance scoped, non-static, $this used -Warning: Cannot unbind $this of closure using $this in %s on line %d +Warning: Cannot unbind $this of closure using $this, this will be an error in PHP 9 in %s on line %d instance scoped, static, $this used instance scoped, non-static, $this not used static scoped, non-static, $this used diff --git a/Zend/tests/038.phpt b/Zend/tests/closures/closure_array_key_error.phpt similarity index 100% rename from Zend/tests/038.phpt rename to Zend/tests/closures/closure_array_key_error.phpt diff --git a/Zend/tests/036.phpt b/Zend/tests/closures/closure_array_offset_error.phpt similarity index 100% rename from Zend/tests/036.phpt rename to Zend/tests/closures/closure_array_offset_error.phpt diff --git a/Zend/tests/closures/closure_call.phpt b/Zend/tests/closures/closure_call.phpt index f665c67ff691f..cfc5f51af9661 100644 --- a/Zend/tests/closures/closure_call.phpt +++ b/Zend/tests/closures/closure_call.phpt @@ -61,7 +61,7 @@ int(0) int(0) int(3) -Warning: Cannot bind closure to scope of internal class stdClass in %s line %d +Warning: Cannot bind closure to scope of internal class stdClass, this will be an error in PHP 9 in %s line %d NULL int(21) int(3) diff --git a/Zend/tests/closures/closure_from_callable_rebinding.phpt b/Zend/tests/closures/closure_from_callable_rebinding.phpt index 6fb5c6ffc1d0c..c23841a30c3ae 100644 --- a/Zend/tests/closures/closure_from_callable_rebinding.phpt +++ b/Zend/tests/closures/closure_from_callable_rebinding.phpt @@ -17,4 +17,4 @@ $fn->call(new B); ?> --EXPECTF-- -Warning: Cannot bind method A::method() to object of class B in %s on line %d +Warning: Cannot bind method A::method() to object of class B, this will be an error in PHP 9 in %s on line %d diff --git a/Zend/tests/closures/closure_get_current.phpt b/Zend/tests/closures/closure_get_current.phpt new file mode 100644 index 0000000000000..3024ff355b558 --- /dev/null +++ b/Zend/tests/closures/closure_get_current.phpt @@ -0,0 +1,64 @@ +--TEST-- +Closure::getCurrent() +--FILE-- +getMessage(), "\n"; +} + +function foo() { + var_dump(Closure::getCurrent()); +} + +try { + foo(...)(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +int(1) +int(1) +int(2) +int(2) +int(3) +int(3) +int(4) +int(4) +int(5) +int(5) +int(6) +int(6) +int(7) +int(7) +int(8) +int(8) +int(9) +int(9) +int(10) +int(10) +int(11) +Current function is not a closure +Current function is not a closure diff --git a/Zend/tests/037.phpt b/Zend/tests/closures/closure_static_property_error.phpt similarity index 100% rename from Zend/tests/037.phpt rename to Zend/tests/closures/closure_static_property_error.phpt diff --git a/Zend/tests/closures/gh12073.phpt b/Zend/tests/closures/gh12073.phpt index ef115685ce7d4..811da788d03fc 100644 --- a/Zend/tests/closures/gh12073.phpt +++ b/Zend/tests/closures/gh12073.phpt @@ -2,6 +2,9 @@ GH-12073: Freeing of non-ZMM pointer of incompletely allocated closure --SKIPIF-- +--EXPECT-- +usage1() func1() a1=a1 a2=a2 a3=m3+ +usage1() [function] func1() a1=a1 a2=m2+ a3=m3+ diff --git a/Zend/tests/closures/gh19653_2.phpt b/Zend/tests/closures/gh19653_2.phpt new file mode 100644 index 0000000000000..7eb837dd22c4d --- /dev/null +++ b/Zend/tests/closures/gh19653_2.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-19653 (Closure named argument unpacking between temporary closures can cause a crash) - eval variation +--CREDITS-- +arnaud-lb +--FILE-- + +--EXPECTF-- +int(1) + +Fatal error: Uncaught Error: Unknown named parameter $a in %s:%d +Stack trace: +#0 %s(%d): usage1(Object(Closure)) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/concat/bug79836.phpt b/Zend/tests/concat/bug79836.phpt index 5fb07396762f5..87db276337098 100644 --- a/Zend/tests/concat/bug79836.phpt +++ b/Zend/tests/concat/bug79836.phpt @@ -8,6 +8,7 @@ $counter = 0; ob_start(function ($buffer) use (&$c, &$counter) { $c = 0; ++$counter; + return ''; }, 1); $c .= []; $c .= []; diff --git a/Zend/tests/concat/bug79836_1.phpt b/Zend/tests/concat/bug79836_1.phpt index 86e7f47671849..972b387235698 100644 --- a/Zend/tests/concat/bug79836_1.phpt +++ b/Zend/tests/concat/bug79836_1.phpt @@ -7,6 +7,7 @@ opcache.optimization_level = 0x7FFEBFFF & ~0x400 $x = 'non-empty'; ob_start(function () use (&$c) { $c = 0; + return ''; }, 1); $c = []; $x = $c . $x; diff --git a/Zend/tests/concat/bug79836_2.phpt b/Zend/tests/concat/bug79836_2.phpt index b02fcc13ea11b..de528e5c42fac 100644 --- a/Zend/tests/concat/bug79836_2.phpt +++ b/Zend/tests/concat/bug79836_2.phpt @@ -6,6 +6,7 @@ $c = str_repeat("abcd", 10); ob_start(function () use (&$c) { $c = 0; + return ''; }, 1); class X { diff --git a/Zend/tests/constants/008.phpt b/Zend/tests/constants/008.phpt index f690cee8e9835..14e074e5d30ac 100644 --- a/Zend/tests/constants/008.phpt +++ b/Zend/tests/constants/008.phpt @@ -27,13 +27,13 @@ echo "Done\n"; --EXPECTF-- TypeError: define(): Argument #1 ($constant_name) must be of type string, array given -Warning: Constant TRUE already defined in %s on line %d +Warning: Constant TRUE already defined, this will be an error in PHP 9 in %s on line %d bool(false) bool(true) bool(true) bool(true) -Warning: Constant test const already defined in %s on line %d +Warning: Constant test const already defined, this will be an error in PHP 9 in %s on line %d bool(false) bool(true) bool(true) diff --git a/Zend/tests/constants/class_constants_005.phpt b/Zend/tests/constants/class_constants_005.phpt index de53c2c0caa54..7accce13f208b 100644 --- a/Zend/tests/constants/class_constants_005.phpt +++ b/Zend/tests/constants/class_constants_005.phpt @@ -4,7 +4,7 @@ String interning during constants substitution opcache.enable_cli=0 --FILE-- diff --git a/Zend/tests/constants/constants_001.phpt b/Zend/tests/constants/constants_001.phpt index 7b274d6fd9c3a..95e22736c10e2 100644 --- a/Zend/tests/constants/constants_001.phpt +++ b/Zend/tests/constants/constants_001.phpt @@ -17,7 +17,7 @@ var_dump(constant('1foo')); ?> --EXPECTF-- -Warning: Constant 1 already defined in %s on line %d +Warning: Constant 1 already defined, this will be an error in PHP 9 in %s on line %d int(2) int(2) int(2) diff --git a/Zend/tests/constants/constants_004.phpt b/Zend/tests/constants/constants_004.phpt index e981415361253..b1482a50ece17 100644 --- a/Zend/tests/constants/constants_004.phpt +++ b/Zend/tests/constants/constants_004.phpt @@ -10,4 +10,4 @@ const foo = 2; ?> --EXPECTF-- -Warning: Constant foo\foo already defined in %s on line %d +Warning: Constant foo\foo already defined, this will be an error in PHP 9 in %s on line %d diff --git a/Zend/tests/constants/constants_008.phpt b/Zend/tests/constants/constants_008.phpt index 17c6904579caf..857589ce23ddd 100644 --- a/Zend/tests/constants/constants_008.phpt +++ b/Zend/tests/constants/constants_008.phpt @@ -13,5 +13,5 @@ if (defined('a')) { ?> --EXPECTF-- -Warning: Constant a already defined in %s on line %d +Warning: Constant a already defined, this will be an error in PHP 9 in %s on line %d 2 diff --git a/Zend/tests/constants/gh18850.inc b/Zend/tests/constants/gh18850.inc new file mode 100644 index 0000000000000..08099278ea3f2 --- /dev/null +++ b/Zend/tests/constants/gh18850.inc @@ -0,0 +1,5 @@ + +--EXPECT-- +int(62) +int(62) diff --git a/Zend/tests/constants/halt_compiler/bug53305.phpt b/Zend/tests/constants/halt_compiler/bug53305.phpt index c76b582e244a9..abf40d9fd6204 100644 --- a/Zend/tests/constants/halt_compiler/bug53305.phpt +++ b/Zend/tests/constants/halt_compiler/bug53305.phpt @@ -14,6 +14,6 @@ var_dump(constant('__COMPILER_HALT_OFFSET__1'.chr(0))); ?> --EXPECTF-- -Warning: Constant __COMPILER_HALT_OFFSET__ already defined in %s on line %d +Warning: Constant __COMPILER_HALT_OFFSET__ already defined, this will be an error in PHP 9 in %s on line %d int(1) int(4) diff --git a/Zend/tests/constants/halt_compiler/halt_compiler3.phpt b/Zend/tests/constants/halt_compiler/halt_compiler3.phpt index ff25b13333639..412c8cf2220ef 100644 --- a/Zend/tests/constants/halt_compiler/halt_compiler3.phpt +++ b/Zend/tests/constants/halt_compiler/halt_compiler3.phpt @@ -5,4 +5,4 @@ __HALT_COMPILER(); bad define() of __COMPILER_HALT_OFFSET__ 1 define ('__COMPILER_HALT_OFFSET__', 1); ?> --EXPECTF-- -Warning: Constant __COMPILER_HALT_OFFSET__ already defined in %s on line %d +Warning: Constant __COMPILER_HALT_OFFSET__ already defined, this will be an error in PHP 9 in %s on line %d diff --git a/Zend/tests/constants/halt_compiler/halt_compiler4.phpt b/Zend/tests/constants/halt_compiler/halt_compiler4.phpt index bb96f25ed96b7..2a1997eca22d8 100644 --- a/Zend/tests/constants/halt_compiler/halt_compiler4.phpt +++ b/Zend/tests/constants/halt_compiler/halt_compiler4.phpt @@ -7,4 +7,4 @@ __HALT_COMPILER(); ?> ==DONE== --EXPECTF-- -Warning: Constant __COMPILER_HALT_OFFSET__ already defined in %s on line %d +Warning: Constant __COMPILER_HALT_OFFSET__ already defined, this will be an error in PHP 9 in %s on line %d diff --git a/Zend/tests/ctor_promotion/ctor_promotion_callable_type.phpt b/Zend/tests/ctor_promotion/ctor_promotion_callable_type.phpt index ae10512ad54a3..85f36bc727bf5 100644 --- a/Zend/tests/ctor_promotion/ctor_promotion_callable_type.phpt +++ b/Zend/tests/ctor_promotion/ctor_promotion_callable_type.phpt @@ -4,9 +4,11 @@ Type of promoted property may not be callable --EXPECTF-- -Fatal error: Property Test::$callable cannot have type callable in %s on line %d +Fatal error: Property Test::$callable cannot have type callable in %s on line 5 diff --git a/Zend/tests/debug_info/debug_info.phpt b/Zend/tests/debug_info/debug_info.phpt index 6f559eb40b7a9..bff5876777ba2 100644 --- a/Zend/tests/debug_info/debug_info.phpt +++ b/Zend/tests/debug_info/debug_info.phpt @@ -36,5 +36,7 @@ object(Foo)#%d (3) { ["c":"Foo":private]=> int(3) } + +Deprecated: Returning null from Bar::__debugInfo() is deprecated, return an empty array instead in %s on line %d object(Bar)#%d (0) { } diff --git a/Zend/tests/debug_info/recursion_return_null.phpt b/Zend/tests/debug_info/recursion_return_null.phpt new file mode 100644 index 0000000000000..b6ca9c824cb72 --- /dev/null +++ b/Zend/tests/debug_info/recursion_return_null.phpt @@ -0,0 +1,31 @@ +--TEST-- +Testing __debugInfo() magic method +--FILE-- + +--EXPECTF-- +in handler + +Deprecated: Returning null from Foo::__debugInfo() is deprecated, return an empty array instead in %s on line %d +object(Foo)#3 (0) { +} +object(Foo)#2 (0) { +} diff --git a/Zend/tests/declare/gh18033_2.phpt b/Zend/tests/declare/gh18033_2.phpt index 8fdcff1b51e6c..39fb46144eed5 100644 --- a/Zend/tests/declare/gh18033_2.phpt +++ b/Zend/tests/declare/gh18033_2.phpt @@ -11,6 +11,7 @@ ob_start(function() { register_tick_function( function() { } ); + return ''; }); ?> --EXPECT-- diff --git a/Zend/tests/disable_classes_warning.phpt b/Zend/tests/disable_classes_warning.phpt new file mode 100644 index 0000000000000..c3692bf52972f --- /dev/null +++ b/Zend/tests/disable_classes_warning.phpt @@ -0,0 +1,27 @@ +--TEST-- +Check that warning is emitted when disabling classes +--INI-- +disable_classes=Exception +--FILE-- + +--EXPECTF-- +object(Exception)#1 (7) { + ["message":protected]=> + string(0) "" + ["string":"Exception":private]=> + string(0) "" + ["code":protected]=> + int(0) + ["file":protected]=> + string(%d) "%s" + ["line":protected]=> + int(2) + ["trace":"Exception":private]=> + array(0) { + } + ["previous":"Exception":private]=> + NULL +} diff --git a/Zend/tests/025.phpt b/Zend/tests/dynamic_call/dynamic_method_calls.phpt similarity index 100% rename from Zend/tests/025.phpt rename to Zend/tests/dynamic_call/dynamic_method_calls.phpt diff --git a/Zend/tests/027.phpt b/Zend/tests/dynamic_call/variable_variables_curly_syntax.phpt similarity index 71% rename from Zend/tests/027.phpt rename to Zend/tests/dynamic_call/variable_variables_curly_syntax.phpt index a862d689e1a84..217ad5a3a304e 100644 --- a/Zend/tests/027.phpt +++ b/Zend/tests/dynamic_call/variable_variables_curly_syntax.phpt @@ -17,6 +17,8 @@ $strtoupper = 'strtolower'; var_dump(${${++$a}}('FOO') == 'foo'); ?> ---EXPECT-- +--EXPECTF-- bool(true) + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d bool(true) diff --git a/Zend/tests/023.phpt b/Zend/tests/dynamic_call/variable_variables_function_names.phpt similarity index 100% rename from Zend/tests/023.phpt rename to Zend/tests/dynamic_call/variable_variables_function_names.phpt diff --git a/Zend/tests/enum/__sleep.phpt b/Zend/tests/enum/__sleep.phpt index 4da08e6a4d3f2..3a50304bef608 100644 --- a/Zend/tests/enum/__sleep.phpt +++ b/Zend/tests/enum/__sleep.phpt @@ -13,4 +13,6 @@ enum Foo { ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Fatal error: Enum Foo cannot include magic method __sleep in %s on line %d diff --git a/Zend/tests/enum/__wakeup.phpt b/Zend/tests/enum/__wakeup.phpt index 8aea17ae53fd3..57b575e89f427 100644 --- a/Zend/tests/enum/__wakeup.phpt +++ b/Zend/tests/enum/__wakeup.phpt @@ -13,4 +13,6 @@ enum Foo { ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Fatal error: Enum Foo cannot include magic method __wakeup in %s on line %d diff --git a/Zend/tests/enum/backed-from-unknown-hash.phpt b/Zend/tests/enum/backed-from-unknown-hash.phpt index eb5938d0d6532..bc82a8d63350c 100644 --- a/Zend/tests/enum/backed-from-unknown-hash.phpt +++ b/Zend/tests/enum/backed-from-unknown-hash.phpt @@ -13,5 +13,6 @@ $s++; var_dump(Foo::from($s)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d enum(Foo::Bar) diff --git a/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt b/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt index 80ffe1dc3908e..133144edfac6e 100644 --- a/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt +++ b/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt @@ -13,5 +13,6 @@ $s++; var_dump(Foo::tryFrom($s)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d enum(Foo::Bar) diff --git a/Zend/tests/enum/spl-object-storage.phpt b/Zend/tests/enum/spl-object-storage.phpt index 7c72299c348e4..10da018b8426d 100644 --- a/Zend/tests/enum/spl-object-storage.phpt +++ b/Zend/tests/enum/spl-object-storage.phpt @@ -16,8 +16,8 @@ $storage[Foo::Baz] = 'Baz'; var_dump($storage[Foo::Bar]); var_dump($storage[Foo::Baz]); -var_dump($storage->contains(Foo::Bar)); -var_dump($storage->contains(Foo::Qux)); +var_dump($storage->offsetExists(Foo::Bar)); +var_dump($storage->offsetExists(Foo::Qux)); $serialized = serialize($storage); var_dump($serialized); diff --git a/Zend/tests/errmsg/errmsg_021.phpt b/Zend/tests/errmsg/errmsg_021.phpt deleted file mode 100644 index 7514e68359044..0000000000000 --- a/Zend/tests/errmsg/errmsg_021.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -errmsg: disabled class ---INI-- -disable_classes=stdclass ---FILE-- - ---EXPECTF-- -Warning: test() has been disabled for security reasons in %s on line %d -Done diff --git a/Zend/tests/exceptions/bug26698.phpt b/Zend/tests/exceptions/bug26698.phpt index 834e0b77c24f5..8155f20905951 100644 --- a/Zend/tests/exceptions/bug26698.phpt +++ b/Zend/tests/exceptions/bug26698.phpt @@ -3,8 +3,6 @@ Bug #26698 (Thrown exceptions while evaluating argument to pass as parameter cra --FILE-- - string(16) "withStaticMethod" + string(33) "AutoloadedClass::withStaticMethod" } Called AutoloadedClass::withStaticMethod diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt index efffa4a1d366a..54c96c915635d 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_001.phpt @@ -1,5 +1,5 @@ --TEST-- -FCC in initializer errors for static reference to instance method. +FCC in initializer warns for static reference to trait method. --FILE-- - string(8) "myMethod" + string(13) "Foo::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt index d36f7c97651e0..97831a8d65f0e 100644 --- a/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt +++ b/Zend/tests/first_class_callable/constexpr/error_static_call_trait_method_002.phpt @@ -1,5 +1,5 @@ --TEST-- -FCC in initializer errors for static reference to instance method (Exception). +FCC in initializer emits deprecation for static reference to trait method (Exception). --FILE-- getClosureCalledClass()); + var_dump($r->getClosureScopeClass()); + } + } +} + +foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) { + foreach ($reflectionAttribute->newInstance()->value as $fn) { + $r = new \ReflectionFunction($fn); + var_dump($r->getClosureCalledClass()); + var_dump($r->getClosureScopeClass()); + } +} +echo "=======\n"; +C::foo(); + +?> +--EXPECTF-- +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "G" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +NULL +NULL +======= +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "G" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "F" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +object(ReflectionClass)#%d (1) { + ["name"]=> + string(1) "C" +} +NULL +NULL diff --git a/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt b/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt index 3959efbd16a05..1776cd8f319de 100644 --- a/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt +++ b/Zend/tests/first_class_callable/constexpr/property_initializer_scope_003.phpt @@ -23,7 +23,7 @@ var_dump(($c->d)("abc")); --EXPECTF-- object(Closure)#%d (2) { ["function"]=> - string(11) "C::myMethod" + string(11) "P::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/tests/first_class_callable/constexpr/static_call.phpt b/Zend/tests/first_class_callable/constexpr/static_call.phpt index 26761a041a4cc..2c6d3aa92b52f 100644 --- a/Zend/tests/first_class_callable/constexpr/static_call.phpt +++ b/Zend/tests/first_class_callable/constexpr/static_call.phpt @@ -19,7 +19,7 @@ var_dump(Closure); --EXPECTF-- object(Closure)#%d (2) { ["function"]=> - string(8) "myMethod" + string(13) "Foo::myMethod" ["parameter"]=> array(1) { ["$foo"]=> diff --git a/Zend/tests/foreach/foreach_list_002.phpt b/Zend/tests/foreach/foreach_list_002.phpt index 1c693651fdc4b..62231f8471482 100644 --- a/Zend/tests/foreach/foreach_list_002.phpt +++ b/Zend/tests/foreach/foreach_list_002.phpt @@ -7,16 +7,48 @@ foreach (array(array(1,2), array(3,4)) as list($a, )) { var_dump($a); } +echo "Array of strings:\n"; $array = [['a', 'b'], 'c', 'd']; foreach($array as list(, $a)) { var_dump($a); } +echo "Array of ints:\n"; +$array = [[5, 6], 10, 20]; + +foreach($array as list(, $a)) { + var_dump($a); +} + +echo "Array of nulls:\n"; +$array = [[null, null], null, null]; + +foreach($array as list(, $a)) { + var_dump($a); +} + ?> ---EXPECT-- +--EXPECTF-- int(1) int(3) +Array of strings: string(1) "b" + +Warning: Cannot use string as array in %s on line %d +NULL + +Warning: Cannot use string as array in %s on line %d +NULL +Array of ints: +int(6) + +Warning: Cannot use int as array in %s on line %d +NULL + +Warning: Cannot use int as array in %s on line %d +NULL +Array of nulls: +NULL NULL NULL diff --git a/Zend/tests/002.phpt b/Zend/tests/func_get_arg_basic.phpt similarity index 98% rename from Zend/tests/002.phpt rename to Zend/tests/func_get_arg_basic.phpt index 7c2ff7b4d389d..ec06a5c20f4df 100644 --- a/Zend/tests/002.phpt +++ b/Zend/tests/func_get_arg_basic.phpt @@ -104,7 +104,7 @@ int(10) func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function int(1) func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function -Exception: Too few arguments to function test2(), 0 passed in %s002.php on line %d and exactly 1 expected +Exception: Too few arguments to function test2(), 0 passed in %s on line %d and exactly 1 expected int(1) int(2) func_get_arg(): Argument #1 ($position) must be less than the number of the arguments passed to the currently executed function diff --git a/Zend/tests/020.phpt b/Zend/tests/func_get_arg_invalid.phpt similarity index 100% rename from Zend/tests/020.phpt rename to Zend/tests/func_get_arg_invalid.phpt diff --git a/Zend/tests/003.phpt b/Zend/tests/func_get_args_basic.phpt similarity index 93% rename from Zend/tests/003.phpt rename to Zend/tests/func_get_args_basic.phpt index 3931628e9a9ca..54ddf1b40c921 100644 --- a/Zend/tests/003.phpt +++ b/Zend/tests/func_get_args_basic.phpt @@ -59,7 +59,7 @@ array(1) { [0]=> int(1) } -Exception: Too few arguments to function test2(), 0 passed in %s003.php on line %d and exactly 1 expected +Exception: Too few arguments to function test2(), 0 passed in %s on line %d and exactly 1 expected array(2) { [0]=> int(1) @@ -68,7 +68,7 @@ array(2) { } array(0) { } -Exception: Too few arguments to function test3(), 1 passed in %s003.php on line %d and exactly 2 expected +Exception: Too few arguments to function test3(), 1 passed in %s on line %d and exactly 2 expected array(2) { [0]=> int(1) diff --git a/Zend/tests/001.phpt b/Zend/tests/func_num_args_basic.phpt similarity index 100% rename from Zend/tests/001.phpt rename to Zend/tests/func_num_args_basic.phpt diff --git a/Zend/tests/028.phpt b/Zend/tests/function_call_array_item.phpt similarity index 100% rename from Zend/tests/028.phpt rename to Zend/tests/function_call_array_item.phpt diff --git a/Zend/tests/gc/bug67314.phpt b/Zend/tests/gc/bug67314.phpt index 8077b01881b0a..33dc01e90c0a8 100644 --- a/Zend/tests/gc/bug67314.phpt +++ b/Zend/tests/gc/bug67314.phpt @@ -17,7 +17,11 @@ echo "ok\n"; ?> --EXPECTF-- Warning: Undefined variable $i in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d made it once Warning: Undefined variable $i in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d ok diff --git a/Zend/tests/gc/gc_046.phpt b/Zend/tests/gc/gc_046.phpt index d5024737365b1..8d48438535217 100644 --- a/Zend/tests/gc/gc_046.phpt +++ b/Zend/tests/gc/gc_046.phpt @@ -20,5 +20,6 @@ $action->filter(); $action->filter(); ?> DONE ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d DONE diff --git a/Zend/tests/009.phpt b/Zend/tests/get_class_basic.phpt similarity index 100% rename from Zend/tests/009.phpt rename to Zend/tests/get_class_basic.phpt diff --git a/Zend/tests/get_included_files_basic.inc b/Zend/tests/get_included_files_basic.inc new file mode 100644 index 0000000000000..406acaee6e461 --- /dev/null +++ b/Zend/tests/get_included_files_basic.inc @@ -0,0 +1,3 @@ + diff --git a/Zend/tests/014.phpt b/Zend/tests/get_included_files_basic.phpt similarity index 74% rename from Zend/tests/014.phpt rename to Zend/tests/get_included_files_basic.phpt index c02fee93856f1..be595a592621a 100644 --- a/Zend/tests/014.phpt +++ b/Zend/tests/get_included_files_basic.phpt @@ -5,13 +5,13 @@ get_included_files() tests var_dump(get_included_files()); -include(__DIR__."/014.inc"); +include(__DIR__."/get_included_files_basic.inc"); var_dump(get_included_files()); -include_once(__DIR__."/014.inc"); +include_once(__DIR__."/get_included_files_basic.inc"); var_dump(get_included_files()); -include(__DIR__."/014.inc"); +include(__DIR__."/get_included_files_basic.inc"); var_dump(get_included_files()); echo "Done\n"; diff --git a/Zend/tests/010.phpt b/Zend/tests/get_parent_class_basic.phpt similarity index 100% rename from Zend/tests/010.phpt rename to Zend/tests/get_parent_class_basic.phpt diff --git a/Zend/tests/gh11189.phpt b/Zend/tests/gh11189.phpt index f1c877f20ee47..9f8202b6102b3 100644 --- a/Zend/tests/gh11189.phpt +++ b/Zend/tests/gh11189.phpt @@ -2,6 +2,9 @@ GH-11189: Exceeding memory limit in zend_hash_do_resize leaves the array in an invalid state (packed array) --SKIPIF-- --INI-- @@ -15,6 +18,7 @@ ob_start(function() { $a[] = 2; } fwrite(STDOUT, "Success"); + return ''; }); $a = []; diff --git a/Zend/tests/gh11189_1.phpt b/Zend/tests/gh11189_1.phpt index 53727908e5e2a..d5b4ee92b62d6 100644 --- a/Zend/tests/gh11189_1.phpt +++ b/Zend/tests/gh11189_1.phpt @@ -2,6 +2,9 @@ GH-11189: Exceeding memory limit in zend_hash_do_resize leaves the array in an invalid state (not packed array) --SKIPIF-- --INI-- @@ -15,6 +18,7 @@ ob_start(function() { $a[] = 2; } fwrite(STDOUT, "Success"); + return ''; }); $a = ["not packed" => 1]; diff --git a/Zend/tests/gh16408.phpt b/Zend/tests/gh16408.phpt index f28c6435bfe73..09d9e8cbb5249 100644 --- a/Zend/tests/gh16408.phpt +++ b/Zend/tests/gh16408.phpt @@ -6,6 +6,7 @@ $counter = 0; ob_start(function ($buffer) use (&$c, &$counter) { $c = 0; ++$counter; + return ''; }, 1); $c .= []; $c .= []; diff --git a/Zend/tests/gh18581.phpt b/Zend/tests/gh18581.phpt new file mode 100644 index 0000000000000..cc5c0fff02e92 --- /dev/null +++ b/Zend/tests/gh18581.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-18581: Coerce numeric string keys from iterators when argument unpacking +--FILE-- + 'first'; + yield '101' => 'second'; + yield '102' => 'third'; + yield 'named' => 'fourth'; +} + +function test($x = null, $y = null, ...$z) { + var_dump($x, $y, $z); + var_dump($z[0]); + var_dump($z['named']); +} + +test(...g()); + +?> +--EXPECT-- +string(5) "first" +string(6) "second" +array(2) { + [0]=> + string(5) "third" + ["named"]=> + string(6) "fourth" +} +string(5) "third" +string(6) "fourth" diff --git a/Zend/tests/gh18736.phpt b/Zend/tests/gh18736.phpt new file mode 100644 index 0000000000000..f397ee39a310b --- /dev/null +++ b/Zend/tests/gh18736.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-18736: Circumvented type check with return by ref + finally +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +test(): Return value must be of type int, string returned diff --git a/Zend/tests/gh19044.phpt b/Zend/tests/gh19044.phpt new file mode 100644 index 0000000000000..3477dd3c8b08a --- /dev/null +++ b/Zend/tests/gh19044.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype +--FILE-- +foo; } +} + +var_dump(C2::foo(new C2)); +var_dump(C2::foo(new C1)); + +?> +--EXPECT-- +int(2) +int(1) diff --git a/Zend/tests/gh19053.phpt b/Zend/tests/gh19053.phpt new file mode 100644 index 0000000000000..7c82f1bc5f412 --- /dev/null +++ b/Zend/tests/gh19053.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-19053: Incorrect properties_info_table for abstract properties +--FILE-- + 2; } +} + +$c = new C; +var_dump($c); + +?> +--EXPECTF-- +object(C)#%d (0) { + ["foo"]=> + uninitialized(mixed) +} diff --git a/Zend/tests/gh19280.phpt b/Zend/tests/gh19280.phpt new file mode 100644 index 0000000000000..d73fc91b623fa --- /dev/null +++ b/Zend/tests/gh19280.phpt @@ -0,0 +1,81 @@ +--TEST-- +GH-19280: Stale nInternalPosition on rehashing +--FILE-- += 0; $i--) { + $a[$i] = $i; + } + for ($i = 0; $i <= 47; $i++) { + next($a); + } + for ($i = 48; $i >= 2; $i--) { + unset($a[$i]); + } + var_dump(key($a)); + $a[64] = 64; + var_dump(key($a)); +} + +rehash_packed(); +rehash_packed_iterated(); +rehash_string(); +rehash_int(); + +?> +--EXPECT-- +int(62) +int(62) +int(62) +int(62) +string(32) "44f683a84163b3523afe57c2e008bc8c" +string(32) "44f683a84163b3523afe57c2e008bc8c" +int(1) +int(1) diff --git a/Zend/tests/gh19304.phpt b/Zend/tests/gh19304.phpt new file mode 100644 index 0000000000000..47e20af64623a --- /dev/null +++ b/Zend/tests/gh19304.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-19304: Incorrect anonymous class type name assertion +--FILE-- +v = 0; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Cannot assign int to property class@anonymous::$v of type self diff --git a/Zend/tests/gh19305-001.phpt b/Zend/tests/gh19305-001.phpt new file mode 100644 index 0000000000000..4c9ee37473e34 --- /dev/null +++ b/Zend/tests/gh19305-001.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19305 001: Operands may be released during comparison +--FILE-- + 'test', + 'bar' => 2, +]; +$b = (object)[ + 'foo' => new class { + public function __toString() { + global $a, $b; + $a = $b = null; + return ''; + } + }, + 'bar' => 2, +]; + +// Comparison of $a->foo and $b->foo calls __toString(), which releases +// both $a and $b. +var_dump($a > $b); + +?> +--EXPECT-- +bool(true) diff --git a/Zend/tests/gh19305-002.phpt b/Zend/tests/gh19305-002.phpt new file mode 100644 index 0000000000000..790156191317b --- /dev/null +++ b/Zend/tests/gh19305-002.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19305 002: Operands may be released during comparison +--FILE-- + 'test', + 'bar' => 2, +]; +$b = [ + 'foo' => new class { + public function __toString() { + global $a, $b; + $a = $b = null; + return ''; + } + }, + 'bar' => 2, +]; + +// Comparison of $a['foo'] and $b['foo'] calls __toString(), which releases +// both $a and $b. +var_dump($a > $b); + +?> +--EXPECT-- +bool(true) diff --git a/Zend/tests/gh19305-003.phpt b/Zend/tests/gh19305-003.phpt new file mode 100644 index 0000000000000..7b071156ef8e3 --- /dev/null +++ b/Zend/tests/gh19305-003.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-19305 003: Operands may be released during comparison +--SKIPIF-- + +--FILE-- +newLazyProxy(function () { return new C; }); + +// Comparison calls initializers, which releases $o +var_dump($o > +$r->newLazyGhost(function () { + global $o; + $o = null; +})); + +?> +--EXPECT-- +bool(false) diff --git a/Zend/tests/gh19306.phpt b/Zend/tests/gh19306.phpt new file mode 100644 index 0000000000000..e19735d94c846 --- /dev/null +++ b/Zend/tests/gh19306.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-19306: Generator suspended in yield from may be resumed +--FILE-- +next(); + echo "Fiber return\n"; +}); +$fiber->start(); +echo "Fiber suspended\n"; +try { + $a->next(); +} catch (Throwable $t) { + echo $t->getMessage(), "\n"; +} +echo "Destroying fiber\n"; +$fiber = null; +echo "Shutdown\n"; +?> +--EXPECT-- +Fiber start +Fiber suspended +Cannot resume an already running generator +Destroying fiber +Shutdown diff --git a/Zend/tests/gh19326.phpt b/Zend/tests/gh19326.phpt new file mode 100644 index 0000000000000..335fdd382ea67 --- /dev/null +++ b/Zend/tests/gh19326.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-19326: Calling Generator::throw() on a running generator with a non-Generator delegate crashes +--FILE-- +rewind(); + +$fiber = new Fiber(function () use ($b) { + $b->next(); +}); + +$fiber->start(); + +try { + $b->throw(new Exception('test')); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +$fiber->resume(); + +?> +--EXPECT-- +Cannot resume an already running generator diff --git a/Zend/tests/gh19543-001.phpt b/Zend/tests/gh19543-001.phpt new file mode 100644 index 0000000000000..411140ea5d706 --- /dev/null +++ b/Zend/tests/gh19543-001.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-19543 001: GC treats ZEND_WEAKREF_TAG_MAP references as WeakMap references +--EXTENSIONS-- +zend_test +--FILE-- + +==DONE== +--EXPECT-- +==DONE== diff --git a/Zend/tests/gh19543-002.phpt b/Zend/tests/gh19543-002.phpt new file mode 100644 index 0000000000000..4a77b9d823da1 --- /dev/null +++ b/Zend/tests/gh19543-002.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-19543 002: GC treats ZEND_WEAKREF_TAG_MAP references as WeakMap references +--EXTENSIONS-- +zend_test +--FILE-- + +==DONE== +--EXPECT-- +==DONE== diff --git a/Zend/tests/gh19613.phpt b/Zend/tests/gh19613.phpt new file mode 100644 index 0000000000000..cd8360b681c79 --- /dev/null +++ b/Zend/tests/gh19613.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-19613: Invalidated array iterator pointer after array separation +--FILE-- + +--EXPECT-- +===DONE=== diff --git a/Zend/tests/gh19679.phpt b/Zend/tests/gh19679.phpt new file mode 100644 index 0000000000000..ab7f3be344d22 --- /dev/null +++ b/Zend/tests/gh19679.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-19679: zend_ssa_range_widening does not converge +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) diff --git a/Zend/tests/in-de-crement/incdec_strings.phpt b/Zend/tests/in-de-crement/incdec_strings.phpt index 9df89536140b2..65b8adf7ee12a 100644 --- a/Zend/tests/in-de-crement/incdec_strings.phpt +++ b/Zend/tests/in-de-crement/incdec_strings.phpt @@ -57,11 +57,11 @@ foreach ($values as $value) { Using increment: Initial value:string(0) "" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(1) "1" Initial value:string(1) " " -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(1) @@ -70,20 +70,28 @@ Result value:float(16.5) Initial value:string(4) "1e10" Result value:float(10000000001) Initial value:string(4) "199A" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(4) "199B" Initial value:string(4) "A199" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(4) "A200" Initial value:string(4) "199Z" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(4) "200A" Initial value:string(4) "Z199" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(4) "Z200" Initial value:string(11) "Hello world" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(11) "Hello worle" Initial value:string(4) "🐘" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(4) "🐘" Using decrement: Initial value:string(0) "" diff --git a/Zend/tests/in-de-crement/incdec_strings_exception.phpt b/Zend/tests/in-de-crement/incdec_strings_exception.phpt index 4214a6a45878a..5acbb1041222a 100644 --- a/Zend/tests/in-de-crement/incdec_strings_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_strings_exception.phpt @@ -41,31 +41,35 @@ foreach ($values as $value) { } ?> --EXPECT-- -Deprecated: Increment on non-alphanumeric string is deprecated +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead string(0) "" Deprecated: Decrement on empty string is deprecated as non-numeric string(0) "" -Deprecated: Increment on non-alphanumeric string is deprecated +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead string(1) " " Deprecated: Decrement on non-numeric string has no effect and is deprecated string(1) " " -string(4) "199B" +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead +string(4) "199A" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "199B" -string(4) "A200" +string(4) "199A" +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead +string(4) "A199" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "A200" -string(4) "200A" +string(4) "A199" +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead +string(4) "199Z" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "200A" -string(4) "Z200" +string(4) "199Z" +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead +string(4) "Z199" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "Z200" -Deprecated: Increment on non-alphanumeric string is deprecated +string(4) "Z199" +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead string(11) "Hello world" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(11) "Hello world" -Deprecated: Increment on non-alphanumeric string is deprecated +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead string(4) "🐘" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "🐘" diff --git a/Zend/tests/in-de-crement/incdec_types.phpt b/Zend/tests/in-de-crement/incdec_types.phpt index dfd850965146a..755b63957ef33 100644 --- a/Zend/tests/in-de-crement/incdec_types.phpt +++ b/Zend/tests/in-de-crement/incdec_types.phpt @@ -63,11 +63,11 @@ Initial value:float(0) Result value:float(1) Initial value:string(0) "" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(1) "1" Initial value:string(1) " " -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(1) diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt index e124bfe907ebc..11a0edac19171 100644 --- a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt @@ -31,8 +31,8 @@ var_dump($x); DONE --EXPECT-- string(1) "1" -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) "foo!" -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "!" DONE diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt index e20159a578cd9..8e63ad6aeed46 100644 --- a/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt @@ -23,8 +23,8 @@ var_dump($x); ?> DONE --EXPECT-- -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) "foo!" -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "!" DONE diff --git a/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt b/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt index 7ca1100fbdde0..f52dff52e6315 100644 --- a/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt +++ b/Zend/tests/in-de-crement/oss-fuzz-62294_globals_unset_after_string_warning.phpt @@ -31,8 +31,8 @@ PRE DEC Decrement on non-numeric string has no effect and is deprecated string(1) " " POST INC -Increment on non-alphanumeric string is deprecated +Increment on non-numeric string is deprecated, use str_increment() instead string(1) " " PRE INC -Increment on non-alphanumeric string is deprecated +Increment on non-numeric string is deprecated, use str_increment() instead string(1) " " diff --git a/Zend/tests/in-de-crement/string_increment_various.phpt b/Zend/tests/in-de-crement/string_increment_various.phpt index 8499d823042b6..d1dd79a03f1be 100644 --- a/Zend/tests/in-de-crement/string_increment_various.phpt +++ b/Zend/tests/in-de-crement/string_increment_various.phpt @@ -53,55 +53,72 @@ var_dump(++$s); // string(3) "5e0" var_dump(++$s); // float(6) ?> --EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "Ba" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "bA" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "B0" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "b0" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "AAa" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "aaA" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "10a" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "10A" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(1) "1" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "-cd" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "Z " -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) " A" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "é" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(15) "あいうえお" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "α" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "ω" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "Α" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(2) "Ω" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(8) "foo1.txu" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(4) "1f.6" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(9) "foo.1.txu" -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(5) "1.f.6" + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "5e0" float(6) diff --git a/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt index d2f27ed323249..31ffea22467be 100644 --- a/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_globals_in_error_handler.phpt @@ -85,23 +85,23 @@ Decrement on type null has no effect, this will change in the next major version NULL Empty string POST INC -Increment on non-alphanumeric string is deprecated +Increment on non-numeric string is deprecated, use str_increment() instead string(0) "" POST DEC Decrement on empty string is deprecated as non-numeric string(0) "" PRE INC -Increment on non-alphanumeric string is deprecated +Increment on non-numeric string is deprecated, use str_increment() instead string(1) "1" PRE DEC Decrement on empty string is deprecated as non-numeric int(-1) Non fill ASCII (only ++) POST INC -Increment on non-alphanumeric string is deprecated +Increment on non-numeric string is deprecated, use str_increment() instead string(4) " ad " PRE INC -Increment on non-alphanumeric string is deprecated +Increment on non-numeric string is deprecated, use str_increment() instead string(4) " ad " Bool POST INC diff --git a/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt index 33d18b9a62797..4d2a4705588aa 100644 --- a/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt +++ b/Zend/tests/in-de-crement/unset_object_property_in_error_handler.phpt @@ -98,23 +98,23 @@ string(87) "Decrement on type null has no effect, this will change in the next m NULL Empty string POST INC -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(0) "" POST DEC string(54) "Decrement on empty string is deprecated as non-numeric" string(0) "" PRE INC -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(1) "1" PRE DEC string(54) "Decrement on empty string is deprecated as non-numeric" int(-1) Non fill ASCII (only ++) POST INC -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) " ad " PRE INC -string(50) "Increment on non-alphanumeric string is deprecated" +string(74) "Increment on non-numeric string is deprecated, use str_increment() instead" string(4) " ad " Bool POST INC diff --git a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt index 6e7e81cd2957c..4bdf4b5d1b956 100644 --- a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt +++ b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt @@ -1,5 +1,5 @@ --TEST-- -Deprecation promoted to exception should result in fatal error during inheritance +Deprecation promoted to exception during inheritance --SKIPIF-- --EXPECTF-- -Fatal error: During inheritance of DateTime: Uncaught Exception: Return type of DateTime@anonymous::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in %s:%d +Fatal error: Uncaught Exception: Return type of DateTime@anonymous::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in %s:%d Stack trace: #0 %s(%d): {closure:%s:%d}(8192, 'Return type of ...', '%s', 8) -#1 {main} in %s on line %d +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt new file mode 100644 index 0000000000000..7a59cca70bd62 --- /dev/null +++ b/Zend/tests/inheritance/deprecation_to_exception_during_inheritance_can_be_caught.phpt @@ -0,0 +1,35 @@ +--TEST-- +Deprecation promoted to exception during inheritance +--SKIPIF-- + +--FILE-- +getMessage()); +} + +var_dump(new C()); + +?> +--EXPECTF-- +Exception: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice +object(C)#%d (3) { + ["date"]=> + string(%d) "%s" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" +} diff --git a/Zend/tests/inheritance/gh15907.phpt b/Zend/tests/inheritance/gh15907.phpt index 8d6dada36ad08..c92e40a4ba30b 100644 --- a/Zend/tests/inheritance/gh15907.phpt +++ b/Zend/tests/inheritance/gh15907.phpt @@ -14,5 +14,8 @@ class C implements Serializable { ?> --EXPECTF-- -Fatal error: During inheritance of C, while implementing Serializable: Uncaught Exception: C implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s:%d -%a +Fatal error: Uncaught Exception: C implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(8192, 'C implements th...', '%s', 7) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/013.phpt b/Zend/tests/interface_exists_basic.phpt similarity index 100% rename from Zend/tests/013.phpt rename to Zend/tests/interface_exists_basic.phpt diff --git a/Zend/tests/isset/isset_array.phpt b/Zend/tests/isset/isset_array.phpt index dfa3fdef51dd7..48e908a36d56d 100644 --- a/Zend/tests/isset/isset_array.phpt +++ b/Zend/tests/isset/isset_array.phpt @@ -42,6 +42,8 @@ bool(true) Deprecated: Implicit conversion from float 0.6 to int loses precision in %s on line %d bool(true) bool(false) + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d diff --git a/Zend/tests/016.phpt b/Zend/tests/isset_non_object.phpt similarity index 100% rename from Zend/tests/016.phpt rename to Zend/tests/isset_non_object.phpt diff --git a/Zend/tests/lazy_objects/oss_fuzz_71446.phpt b/Zend/tests/lazy_objects/oss_fuzz_71446.phpt index ae2db55c73fc1..9d2f3283b9a22 100644 --- a/Zend/tests/lazy_objects/oss_fuzz_71446.phpt +++ b/Zend/tests/lazy_objects/oss_fuzz_71446.phpt @@ -20,3 +20,4 @@ $obj = $reflector->newLazyProxy(function() { serialize($obj); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d diff --git a/Zend/tests/lazy_objects/serialize___sleep.phpt b/Zend/tests/lazy_objects/serialize___sleep.phpt index d21f0fe09c97d..ac92fcb875ca1 100644 --- a/Zend/tests/lazy_objects/serialize___sleep.phpt +++ b/Zend/tests/lazy_objects/serialize___sleep.phpt @@ -36,6 +36,7 @@ try { ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d Init on serialize and successful initialization string(27) "O:1:"C":1:{s:4:"%0C%0b";i:1;}" Init on serialize and failed initialization diff --git a/Zend/tests/lazy_objects/serialize___sleep_initializes.phpt b/Zend/tests/lazy_objects/serialize___sleep_initializes.phpt index ec7657afc6916..fa7c99b5635fe 100644 --- a/Zend/tests/lazy_objects/serialize___sleep_initializes.phpt +++ b/Zend/tests/lazy_objects/serialize___sleep_initializes.phpt @@ -37,6 +37,7 @@ $obj = $reflector->newLazyProxy(function ($obj) { test('Proxy', $obj); --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d # Ghost: string(11) "initializer" string(24) "O:1:"C":1:{s:1:"a";i:1;}" diff --git a/Zend/tests/lazy_objects/serialize___sleep_skip_flag.phpt b/Zend/tests/lazy_objects/serialize___sleep_skip_flag.phpt index 4641fb2a49ac3..2e5bde97a5e6e 100644 --- a/Zend/tests/lazy_objects/serialize___sleep_skip_flag.phpt +++ b/Zend/tests/lazy_objects/serialize___sleep_skip_flag.phpt @@ -35,6 +35,7 @@ $obj = $reflector->newLazyProxy(function ($obj) { test('Proxy', $obj); --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d # Ghost: string(12) "O:1:"C":0:{}" object(C)#%d (0) { diff --git a/Zend/tests/lazy_objects/serialize___sleep_skip_flag_may_initialize.phpt b/Zend/tests/lazy_objects/serialize___sleep_skip_flag_may_initialize.phpt index ed909a875de47..06aeaf4f97b6b 100644 --- a/Zend/tests/lazy_objects/serialize___sleep_skip_flag_may_initialize.phpt +++ b/Zend/tests/lazy_objects/serialize___sleep_skip_flag_may_initialize.phpt @@ -38,6 +38,7 @@ $obj = $reflector->newLazyProxy(function ($obj) { test('Proxy', $obj); --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d # Ghost: string(11) "initializer" int(1) diff --git a/Zend/tests/lazy_objects/skipLazyInitialization.phpt b/Zend/tests/lazy_objects/skipLazyInitialization.phpt index d4d564d9c6532..4fc47b13db671 100644 --- a/Zend/tests/lazy_objects/skipLazyInitialization.phpt +++ b/Zend/tests/lazy_objects/skipLazyInitialization.phpt @@ -227,7 +227,7 @@ getValue(): NULL setRawValueWithoutLazyInitialization(): getValue(): string(5) "value" -## Property [ public $hooked = NULL ] +## Property [ public $hooked = NULL { get; set; } ] skipInitializerForProperty(): getValue(): NULL @@ -235,7 +235,7 @@ getValue(): NULL setRawValueWithoutLazyInitialization(): getValue(): string(5) "value" -## Property [ public $virtual ] +## Property [ public virtual $virtual { get; set; } ] skipInitializerForProperty(): ReflectionException: Can not use skipLazyInitialization on virtual property A::$virtual @@ -324,7 +324,7 @@ getValue(): NULL setRawValueWithoutLazyInitialization(): getValue(): string(5) "value" -## Property [ public $hooked = NULL ] +## Property [ public $hooked = NULL { get; set; } ] skipInitializerForProperty(): getValue(): NULL @@ -332,7 +332,7 @@ getValue(): NULL setRawValueWithoutLazyInitialization(): getValue(): string(5) "value" -## Property [ public $virtual ] +## Property [ public virtual $virtual { get; set; } ] skipInitializerForProperty(): ReflectionException: Can not use skipLazyInitialization on virtual property A::$virtual diff --git a/Zend/tests/list/bug39304.phpt b/Zend/tests/list/bug39304.phpt index a5422d2f4f316..353baa5df01df 100644 --- a/Zend/tests/list/bug39304.phpt +++ b/Zend/tests/list/bug39304.phpt @@ -8,5 +8,9 @@ Bug #39304 (Segmentation fault with list unpacking of string offset) ?> --EXPECTF-- Warning: Uninitialized string offset 0 in %s on line %d + +Warning: Cannot use string as array in %s on line %d + +Warning: Cannot use string as array in %s on line %d NULL NULL diff --git a/Zend/tests/list/destruct_bool.phpt b/Zend/tests/list/destruct_bool.phpt new file mode 100644 index 0000000000000..7553811220c99 --- /dev/null +++ b/Zend/tests/list/destruct_bool.phpt @@ -0,0 +1,18 @@ +--TEST-- +Destructuring with list() a value of type bool +--FILE-- + +--EXPECTF-- +Warning: Cannot use bool as array in %s on line %d + +Warning: Cannot use bool as array in %s on line %d +NULL +NULL diff --git a/Zend/tests/list/destruct_float.phpt b/Zend/tests/list/destruct_float.phpt new file mode 100644 index 0000000000000..6423a5b5668a4 --- /dev/null +++ b/Zend/tests/list/destruct_float.phpt @@ -0,0 +1,18 @@ +--TEST-- +Destructuring with list() a value of type float +--FILE-- + +--EXPECTF-- +Warning: Cannot use float as array in %s on line %d + +Warning: Cannot use float as array in %s on line %d +NULL +NULL diff --git a/Zend/tests/list/destruct_int.phpt b/Zend/tests/list/destruct_int.phpt new file mode 100644 index 0000000000000..e232ecb73982a --- /dev/null +++ b/Zend/tests/list/destruct_int.phpt @@ -0,0 +1,18 @@ +--TEST-- +Destructuring with list() a value of type int +--FILE-- + +--EXPECTF-- +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d +NULL +NULL diff --git a/Zend/tests/list/destruct_null.phpt b/Zend/tests/list/destruct_null.phpt new file mode 100644 index 0000000000000..e89de45a28e83 --- /dev/null +++ b/Zend/tests/list/destruct_null.phpt @@ -0,0 +1,12 @@ +--TEST-- +Destructuring with list() a value of type null +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/tests/list/destruct_object_not_ArrayAccess.phpt b/Zend/tests/list/destruct_object_not_ArrayAccess.phpt new file mode 100644 index 0000000000000..097c2cd2def3e --- /dev/null +++ b/Zend/tests/list/destruct_object_not_ArrayAccess.phpt @@ -0,0 +1,17 @@ +--TEST-- +Destructuring with list() a value of type object (that does not implement ArrayAccess) +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/list/destruct_resource.phpt b/Zend/tests/list/destruct_resource.phpt new file mode 100644 index 0000000000000..8e5576767fe11 --- /dev/null +++ b/Zend/tests/list/destruct_resource.phpt @@ -0,0 +1,18 @@ +--TEST-- +Destructuring with list() a value of type resource +--FILE-- + +--EXPECTF-- +Warning: Cannot use resource as array in %s on line %d + +Warning: Cannot use resource as array in %s on line %d +NULL +NULL diff --git a/Zend/tests/list/destruct_string.phpt b/Zend/tests/list/destruct_string.phpt new file mode 100644 index 0000000000000..b2ea88c65a6cf --- /dev/null +++ b/Zend/tests/list/destruct_string.phpt @@ -0,0 +1,21 @@ +--TEST-- +Destructuring with list() a value of type string +--FILE-- + +--EXPECTF-- +Warning: Cannot use string as array in %s on line %d + +Warning: Cannot use string as array in %s on line %d + +Warning: Cannot use string as array in %s on line %d +NULL +NULL +NULL diff --git a/Zend/tests/list/list_003.phpt b/Zend/tests/list/list_003.phpt deleted file mode 100644 index 4a509f6a828b4..0000000000000 --- a/Zend/tests/list/list_003.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -list() with non-array ---FILE-- - ---EXPECT-- -NULL -NULL -NULL -NULL -NULL diff --git a/Zend/tests/list/list_005.phpt b/Zend/tests/list/list_005.phpt deleted file mode 100644 index 7dc3bf6fa36a6..0000000000000 --- a/Zend/tests/list/list_005.phpt +++ /dev/null @@ -1,50 +0,0 @@ ---TEST-- -Testing list() with several variables ---FILE-- - ---EXPECTF-- -NULL -NULL -NULL ----- -NULL -NULL -NULL ----- - -Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d diff --git a/Zend/tests/list/list_keyed_conversions.phpt b/Zend/tests/list/list_keyed_conversions.phpt index 9798be199894f..637e517d51b90 100644 --- a/Zend/tests/list/list_keyed_conversions.phpt +++ b/Zend/tests/list/list_keyed_conversions.phpt @@ -21,6 +21,8 @@ list(STDIN => $resource) = []; ?> --EXPECTF-- +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d + Deprecated: Implicit conversion from float 1.5 to int loses precision in %s on line %d string(0) "" int(1) diff --git a/Zend/tests/nullsafe_operator/013.phpt b/Zend/tests/nullsafe_operator/013.phpt index 883f6ac24aa8d..ea35399548916 100644 Binary files a/Zend/tests/nullsafe_operator/013.phpt and b/Zend/tests/nullsafe_operator/013.phpt differ diff --git a/Zend/tests/numeric_strings/oss_fuzz_427814456.phpt b/Zend/tests/numeric_strings/oss_fuzz_427814456.phpt new file mode 100644 index 0000000000000..f91563385e9f5 --- /dev/null +++ b/Zend/tests/numeric_strings/oss_fuzz_427814456.phpt @@ -0,0 +1,11 @@ +--TEST-- +OSS-Fuzz #427814456 +--FILE-- + +--EXPECT-- +Done diff --git a/Zend/tests/oct_overflow.phpt b/Zend/tests/oct_overflow.phpt index 512a6abf6643a..b8ce3f40fde11 100644 --- a/Zend/tests/oct_overflow.phpt +++ b/Zend/tests/oct_overflow.phpt @@ -5,7 +5,7 @@ precision=14 --FILE-- +--EXPECTF-- +Using null as an array offset is deprecated, use an empty string instead +Success diff --git a/Zend/tests/operator_unsupported_types.phpt b/Zend/tests/operator_unsupported_types.phpt index ef169bb39fc29..a08032226e5db 100644 --- a/Zend/tests/operator_unsupported_types.phpt +++ b/Zend/tests/operator_unsupported_types.phpt @@ -2104,6 +2104,7 @@ Cannot increment stdClass Cannot decrement stdClass Cannot increment resource Cannot decrement resource +Warning: Increment on non-numeric string is deprecated, use str_increment() instead No error for fop++ Warning: Decrement on non-numeric string has no effect and is deprecated No error for foo-- diff --git a/Zend/tests/oss_fuzz_434346548.phpt b/Zend/tests/oss_fuzz_434346548.phpt new file mode 100644 index 0000000000000..139e36758bc49 --- /dev/null +++ b/Zend/tests/oss_fuzz_434346548.phpt @@ -0,0 +1,22 @@ +--TEST-- +OSS-Fuzz #434346548: Failed assertion with throwing __toString in binary const expr +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +Foo::__toString(): Return value must be of type string, none returned diff --git a/Zend/tests/pipe_operator/gh18965.phpt b/Zend/tests/pipe_operator/gh18965.phpt new file mode 100644 index 0000000000000..8f9eaaebb08aa --- /dev/null +++ b/Zend/tests/pipe_operator/gh18965.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-18965: ASSERT_CHECK avoids pipe lhs free +--INI-- +zend.assertions=0 +--FILE-- + assert(...); +echo "No leak\n"; +?> +--EXPECT-- +No leak diff --git a/Zend/tests/pipe_operator/mixed_callable_call.phpt b/Zend/tests/pipe_operator/mixed_callable_call.phpt index 55bae626f1890..d577f3aaefe69 100644 --- a/Zend/tests/pipe_operator/mixed_callable_call.phpt +++ b/Zend/tests/pipe_operator/mixed_callable_call.phpt @@ -71,7 +71,7 @@ $res1 = 1 |> [StaticTest::class, 'times17'] |> new Times23() |> $times29 - |> fn($x) => times2($x) + |> (fn($x) => times2($x)) ; var_dump($res1); diff --git a/Zend/tests/pipe_operator/oss_fuzz_427814452.phpt b/Zend/tests/pipe_operator/oss_fuzz_427814452.phpt new file mode 100644 index 0000000000000..2ecfbab6348f7 --- /dev/null +++ b/Zend/tests/pipe_operator/oss_fuzz_427814452.phpt @@ -0,0 +1,26 @@ +--TEST-- +OSS-Fuzz #427814452 +--FILE-- + assert(...); +} catch (\AssertionError $e) { + echo $e::class, ": '", $e->getMessage(), "'\n"; +} +try { + 0 |> "assert"(...); +} catch (\AssertionError $e) { + echo $e::class, ": '", $e->getMessage(), "'\n"; +} +try { + false |> ("a"."ssert")(...); +} catch (\AssertionError $e) { + echo $e::class, ": '", $e->getMessage(), "'\n"; +} + +?> +--EXPECT-- +AssertionError: '' +AssertionError: '' +AssertionError: '' diff --git a/Zend/tests/pipe_operator/oss_fuzz_439125710.phpt b/Zend/tests/pipe_operator/oss_fuzz_439125710.phpt new file mode 100644 index 0000000000000..320f55a4e6680 --- /dev/null +++ b/Zend/tests/pipe_operator/oss_fuzz_439125710.phpt @@ -0,0 +1,8 @@ +--TEST-- +OSS-Fuzz #439125710 (Pipe cannot be used in write context) +--FILE-- +y)=y; +?> +--EXPECTF-- +Fatal error: Can't use function return value in write context in %s on line %d diff --git a/Zend/tests/pipe_operator/prec_001.phpt b/Zend/tests/pipe_operator/prec_001.phpt new file mode 100644 index 0000000000000..3bd3397fd3617 --- /dev/null +++ b/Zend/tests/pipe_operator/prec_001.phpt @@ -0,0 +1,12 @@ +--TEST-- +Pipe precedence 001 +--FILE-- + fn($x) => $x < 42 + |> fn($x) => var_dump($x); + +?> +--EXPECTF-- +Fatal error: Arrow functions on the right hand side of |> must be parenthesized in %s on line %d diff --git a/Zend/tests/pipe_operator/prec_002.phpt b/Zend/tests/pipe_operator/prec_002.phpt new file mode 100644 index 0000000000000..00a16e61fed4b --- /dev/null +++ b/Zend/tests/pipe_operator/prec_002.phpt @@ -0,0 +1,12 @@ +--TEST-- +Pipe precedence 002 +--FILE-- + (fn($x) => $x < 42) + |> (fn($x) => var_dump($x)); + +?> +--EXPECT-- +bool(false) diff --git a/Zend/tests/pipe_operator/prec_003.phpt b/Zend/tests/pipe_operator/prec_003.phpt new file mode 100644 index 0000000000000..9200b8014e09f --- /dev/null +++ b/Zend/tests/pipe_operator/prec_003.phpt @@ -0,0 +1,12 @@ +--TEST-- +Pipe precedence 003 +--FILE-- + fn() => print (new Exception)->getTraceAsString() . "\n\n" + |> fn() => print (new Exception)->getTraceAsString() . "\n\n"; + +?> +--EXPECTF-- +Fatal error: Arrow functions on the right hand side of |> must be parenthesized in %s on line %d diff --git a/Zend/tests/pipe_operator/prec_004.phpt b/Zend/tests/pipe_operator/prec_004.phpt new file mode 100644 index 0000000000000..c04f483cdd8db --- /dev/null +++ b/Zend/tests/pipe_operator/prec_004.phpt @@ -0,0 +1,16 @@ +--TEST-- +Pipe precedence 004 +--FILE-- + (fn() => print (new Exception)->getTraceAsString() . "\n\n") + |> (fn() => print (new Exception)->getTraceAsString() . "\n\n"); + +?> +--EXPECTF-- +#0 %s(%d): {closure:%s:%d}(NULL) +#1 {main} + +#0 %s(%d): {closure:%s:%d}(1) +#1 {main} diff --git a/Zend/tests/pipe_operator/prec_005.phpt b/Zend/tests/pipe_operator/prec_005.phpt new file mode 100644 index 0000000000000..0dd262324e3d2 --- /dev/null +++ b/Zend/tests/pipe_operator/prec_005.phpt @@ -0,0 +1,14 @@ +--TEST-- +Pipe precedence 005 +--FILE-- + (fn() => 2)); +} catch (AssertionError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +assert(false && 1 |> (fn() => 2)) diff --git a/Zend/tests/pipe_operator/prec_006.phpt b/Zend/tests/pipe_operator/prec_006.phpt new file mode 100644 index 0000000000000..d7fdf4c9b55b1 --- /dev/null +++ b/Zend/tests/pipe_operator/prec_006.phpt @@ -0,0 +1,13 @@ +--TEST-- +Pipe precedence 006 +--FILE-- + fn ($x) => $x ?? throw new Exception('Value may not be null') + |> fn ($x) => var_dump($x); + +?> +--EXPECTF-- +Fatal error: Arrow functions on the right hand side of |> must be parenthesized in %s on line %d diff --git a/Zend/tests/pipe_operator/prec_007.phpt b/Zend/tests/pipe_operator/prec_007.phpt new file mode 100644 index 0000000000000..c29db8565008f --- /dev/null +++ b/Zend/tests/pipe_operator/prec_007.phpt @@ -0,0 +1,24 @@ +--TEST-- +Pipe precedence 007 +--FILE-- + (fn ($x) => $x ?? throw new Exception('Value may not be null')) + |> (fn ($x) => var_dump($x)); + +$value = null; +$value + |> (fn ($x) => $x ?? throw new Exception('Value may not be null')) + |> (fn ($x) => var_dump($x)); + +?> +--EXPECTF-- +int(42) + +Fatal error: Uncaught Exception: Value may not be null in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(NULL) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/pipe_operator_reference_context.phpt b/Zend/tests/pipe_operator_reference_context.phpt new file mode 100644 index 0000000000000..7d7572e2b2e59 --- /dev/null +++ b/Zend/tests/pipe_operator_reference_context.phpt @@ -0,0 +1,26 @@ +--TEST-- +Fix GH-19476: Pipe operator with function returning by reference +--FILE-- + get_ref(...); +} + +$ref = &test_pipe_ref(); +echo "Before: " . $ref . "\n"; +$ref = "changed"; +echo "After: " . test_pipe_ref() . "\n"; + +?> +--EXPECT-- +Before: original input +After: changed input diff --git a/Zend/tests/011.phpt b/Zend/tests/property_exists_basic.phpt similarity index 100% rename from Zend/tests/011.phpt rename to Zend/tests/property_exists_basic.phpt diff --git a/Zend/tests/property_hooks/cpp.phpt b/Zend/tests/property_hooks/cpp.phpt index 082c182467bcf..1f893d853b8c0 100644 --- a/Zend/tests/property_hooks/cpp.phpt +++ b/Zend/tests/property_hooks/cpp.phpt @@ -24,11 +24,13 @@ var_dump($r->hasDefaultValue()); var_dump($r->getDefaultValue()); ?> ---EXPECT-- +--EXPECTF-- Pre-test Setting Constructor Getting Setting bool(false) + +Deprecated: ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, use ReflectionProperty::hasDefaultValue() to check if the default value exists in %s on line %d NULL diff --git a/Zend/tests/property_hooks/gh19044-1.phpt b/Zend/tests/property_hooks/gh19044-1.phpt new file mode 100644 index 0000000000000..133727c73def8 --- /dev/null +++ b/Zend/tests/property_hooks/gh19044-1.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (common ancestor has a protected setter) +--FILE-- + 1; set {} } +} + +class GrandC1 extends C1 { + public protected(set) mixed $foo { get => 2; set {} } +} + +class C2 extends C1 { + static function foo($c) { return $c->foo += 1; } +} + +var_dump(C2::foo(new GrandC1)); + +?> +--EXPECT-- +int(3) diff --git a/Zend/tests/property_hooks/gh19044-2.phpt b/Zend/tests/property_hooks/gh19044-2.phpt new file mode 100644 index 0000000000000..ed73c60dc5a3a --- /dev/null +++ b/Zend/tests/property_hooks/gh19044-2.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (common ancestor does not have a setter) +--FILE-- + 1; } +} + +class GrandC1 extends C1 { + public protected(set) mixed $foo { get => 2; set {} } +} + +class C2 extends C1 { + static function foo($c) { return $c->foo += 1; } +} + +var_dump(C2::foo(new GrandC1)); + +?> +--EXPECT-- +int(3) diff --git a/Zend/tests/property_hooks/gh19044-3.phpt b/Zend/tests/property_hooks/gh19044-3.phpt new file mode 100644 index 0000000000000..3d4f6789a5a37 --- /dev/null +++ b/Zend/tests/property_hooks/gh19044-3.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (abstract parent defining visibility only takes precedence) +--FILE-- + 2; set {} } +} + +class C2 extends P { + public mixed $foo = 1; + + static function foo($c) { return $c->foo += 1; } +} + +var_dump(C2::foo(new C1)); + +?> +--EXPECT-- +int(3) diff --git a/Zend/tests/property_hooks/gh19044-4.phpt b/Zend/tests/property_hooks/gh19044-4.phpt new file mode 100644 index 0000000000000..e1abf47390831 --- /dev/null +++ b/Zend/tests/property_hooks/gh19044-4.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (abstract parent sets protected(set) with not having grandparent a setter - both inherit from parent) +--FILE-- + 2; set {} } +} + +class C2 extends P { + public mixed $foo = 1; + + static function foo($c) { return $c->foo += 1; } +} + +var_dump(C2::foo(new C1)); + +?> +--EXPECT-- +int(3) diff --git a/Zend/tests/property_hooks/gh19044-5.phpt b/Zend/tests/property_hooks/gh19044-5.phpt new file mode 100644 index 0000000000000..773682961ab41 --- /dev/null +++ b/Zend/tests/property_hooks/gh19044-5.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (abstract parent sets protected(set) with not having grandparent a setter - one inherits from grandparent) +--FILE-- + 2; set {} } +} + +class C2 extends GP { + public mixed $foo = 1; + + static function foo($c) { return $c->foo += 1; } +} + +var_dump(C2::foo(new C1)); + +?> +--EXPECT-- +int(3) diff --git a/Zend/tests/property_hooks/gh19044-6.phpt b/Zend/tests/property_hooks/gh19044-6.phpt new file mode 100644 index 0000000000000..43332698fe9f7 --- /dev/null +++ b/Zend/tests/property_hooks/gh19044-6.phpt @@ -0,0 +1,28 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (abstract parent has implicit set hook) +--FILE-- + $this->foo; } +} + +class C1 extends P { + public protected(set) mixed $foo = 1; +} + +class C2 extends P { + public protected(set) mixed $foo; + + static function foo($c) { return $c->foo += 1; } +} + +var_dump(C2::foo(new C1)); + +?> +--EXPECT-- +int(2) diff --git a/Zend/tests/property_hooks/gh19044-8.phpt b/Zend/tests/property_hooks/gh19044-8.phpt new file mode 100644 index 0000000000000..2fa62e4619f56 --- /dev/null +++ b/Zend/tests/property_hooks/gh19044-8.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-19044: Protected properties must be scoped according to their prototype (hooks variation) +--FILE-- +foo; } +} + +var_dump(C2::foo(new C2)); +var_dump(C2::foo(new C1)); + +?> +--EXPECT-- +int(2) +int(1) diff --git a/Zend/tests/property_hooks/gh19548.phpt b/Zend/tests/property_hooks/gh19548.phpt new file mode 100644 index 0000000000000..d34ed0a74bb2f --- /dev/null +++ b/Zend/tests/property_hooks/gh19548.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-19548: Segfault when using inherited properties and opcache +--FILE-- + +--EXPECT-- +Test passed - no segmentation fault diff --git a/Zend/tests/property_hooks/gh19548_002.phpt b/Zend/tests/property_hooks/gh19548_002.phpt new file mode 100644 index 0000000000000..bba006b81032e --- /dev/null +++ b/Zend/tests/property_hooks/gh19548_002.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-19548: Segfault when using inherited properties and opcache (multiple properties) +--FILE-- + +--EXPECT-- +Multiple property test passed - no segmentation fault diff --git a/Zend/tests/readonly_classes/gh10377_1.phpt b/Zend/tests/readonly_classes/gh10377_1.phpt index ac421cb8a5171..fba1605ff0849 100644 --- a/Zend/tests/readonly_classes/gh10377_1.phpt +++ b/Zend/tests/readonly_classes/gh10377_1.phpt @@ -12,4 +12,4 @@ $readonly_anon = new #[AllowDynamicProperties] readonly class { ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class class@anonymous in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to readonly class class@anonymous in %s on line %d diff --git a/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt b/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt index ace50c572aced..fab37dccfbf61 100644 --- a/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt +++ b/Zend/tests/readonly_classes/readonly_class_dynamic_property_attribute.phpt @@ -10,4 +10,4 @@ readonly class Foo ?> --EXPECTF-- -Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo in %s on line %d +Fatal error: Cannot apply #[\AllowDynamicProperties] to readonly class Foo in %s on line %d diff --git a/Zend/tests/serialize/bug34045.phpt b/Zend/tests/serialize/bug34045.phpt index 61886cf354b67..79625a82a7b8f 100644 --- a/Zend/tests/serialize/bug34045.phpt +++ b/Zend/tests/serialize/bug34045.phpt @@ -24,5 +24,6 @@ $db_str = serialize($db); $db2 = unserialize($db_str); echo "ok\n"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d ok diff --git a/Zend/tests/035.phpt b/Zend/tests/static_global_scope.phpt similarity index 100% rename from Zend/tests/035.phpt rename to Zend/tests/static_global_scope.phpt diff --git a/Zend/tests/005.phpt b/Zend/tests/strcasecmp_basic.phpt similarity index 100% rename from Zend/tests/005.phpt rename to Zend/tests/strcasecmp_basic.phpt diff --git a/Zend/tests/006.phpt b/Zend/tests/strncasecmp_basic.phpt similarity index 100% rename from Zend/tests/006.phpt rename to Zend/tests/strncasecmp_basic.phpt diff --git a/Zend/tests/004.phpt b/Zend/tests/strncmp_basic.phpt similarity index 100% rename from Zend/tests/004.phpt rename to Zend/tests/strncmp_basic.phpt diff --git a/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt b/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt index e5f4b73bb14a2..6e6dc58baad0e 100644 --- a/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt +++ b/Zend/tests/temporary_cleaning/temporary_cleaning_013.phpt @@ -320,5 +320,7 @@ caught Exception 27 caught Exception 28 caught Exception 29 caught Exception 30 + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d caught Exception 31 caught Exception 32 diff --git a/Zend/tests/021.phpt b/Zend/tests/ternary_operator_basic.phpt similarity index 100% rename from Zend/tests/021.phpt rename to Zend/tests/ternary_operator_basic.phpt diff --git a/Zend/tests/traits/bugs/gh13177.phpt b/Zend/tests/traits/bugs/gh13177.phpt index 42ef0ae9d60d7..1787b3c6bd7c2 100644 --- a/Zend/tests/traits/bugs/gh13177.phpt +++ b/Zend/tests/traits/bugs/gh13177.phpt @@ -1,5 +1,11 @@ --TEST-- GH-13177 (PHP 8.3.2: final private constructor not allowed when used in trait) +--SKIPIF-- + --FILE-- +--EXPECTF-- +Deprecated: Non-canonical cast (binary) is deprecated, use the (string) cast instead in %s on line %d +string(2) "42" diff --git a/Zend/tests/type_coercion/type_casts/non_canonical_boolean_cast.phpt b/Zend/tests/type_coercion/type_casts/non_canonical_boolean_cast.phpt new file mode 100644 index 0000000000000..e0db0eec475fd --- /dev/null +++ b/Zend/tests/type_coercion/type_casts/non_canonical_boolean_cast.phpt @@ -0,0 +1,11 @@ +--TEST-- +Non canonical (boolean) cast +--FILE-- + +--EXPECTF-- +Deprecated: Non-canonical cast (boolean) is deprecated, use the (bool) cast instead in %s on line %d +bool(true) diff --git a/Zend/tests/type_coercion/type_casts/non_canonical_double_cast.phpt b/Zend/tests/type_coercion/type_casts/non_canonical_double_cast.phpt new file mode 100644 index 0000000000000..91769a206a475 --- /dev/null +++ b/Zend/tests/type_coercion/type_casts/non_canonical_double_cast.phpt @@ -0,0 +1,11 @@ +--TEST-- +Non canonical (double) cast +--FILE-- + +--EXPECTF-- +Deprecated: Non-canonical cast (double) is deprecated, use the (float) cast instead in %s on line %d +float(42) diff --git a/Zend/tests/type_coercion/type_casts/non_canonical_integer_cast.phpt b/Zend/tests/type_coercion/type_casts/non_canonical_integer_cast.phpt new file mode 100644 index 0000000000000..4f428ff9d53e0 --- /dev/null +++ b/Zend/tests/type_coercion/type_casts/non_canonical_integer_cast.phpt @@ -0,0 +1,11 @@ +--TEST-- +Non canonical (integer) cast +--FILE-- + +--EXPECTF-- +Deprecated: Non-canonical cast (integer) is deprecated, use the (int) cast instead in %s on line %d +int(42) diff --git a/Zend/tests/type_casts/real_cast.phpt b/Zend/tests/type_coercion/type_casts/real_cast.phpt similarity index 100% rename from Zend/tests/type_casts/real_cast.phpt rename to Zend/tests/type_coercion/type_casts/real_cast.phpt diff --git a/Zend/tests/type_casts/string_cast_reference_tostring.phpt b/Zend/tests/type_coercion/type_casts/string_cast_reference_tostring.phpt similarity index 100% rename from Zend/tests/type_casts/string_cast_reference_tostring.phpt rename to Zend/tests/type_coercion/type_casts/string_cast_reference_tostring.phpt diff --git a/Zend/tests/type_declarations/typed_properties_113.phpt b/Zend/tests/type_declarations/typed_properties_113.phpt index cb5c0f9276453..0aecc76f758a4 100644 --- a/Zend/tests/type_declarations/typed_properties_113.phpt +++ b/Zend/tests/type_declarations/typed_properties_113.phpt @@ -19,7 +19,8 @@ foreach ($obj as $k => &$v) { var_dump($obj); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d object(A)#1 (1) { ["foo"]=> &string(2) "42" diff --git a/Zend/tests/type_declarations/typed_properties_114.phpt b/Zend/tests/type_declarations/typed_properties_114.phpt index e771f4c1c1f84..5f3093dd33088 100644 --- a/Zend/tests/type_declarations/typed_properties_114.phpt +++ b/Zend/tests/type_declarations/typed_properties_114.phpt @@ -30,8 +30,11 @@ foreach ($obj as $k => &$v) { var_dump($obj); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d Cannot assign array to reference held by property A::$foo of type string + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d Cannot assign array to reference held by property A::$foo of type string object(A)#1 (1) { ["foo"]=> diff --git a/Zend/tests/type_declarations/typed_properties_115.phpt b/Zend/tests/type_declarations/typed_properties_115.phpt index eb96b3ee88641..6347ee0c35d6c 100644 --- a/Zend/tests/type_declarations/typed_properties_115.phpt +++ b/Zend/tests/type_declarations/typed_properties_115.phpt @@ -22,7 +22,8 @@ try { var_dump($obj); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d Cannot acquire reference to readonly property A::$foo object(A)#1 (1) { ["foo"]=> diff --git a/Zend/tests/033.phpt b/Zend/tests/undefined_multidimensional_array.phpt similarity index 100% rename from Zend/tests/033.phpt rename to Zend/tests/undefined_multidimensional_array.phpt diff --git a/Zend/tests/024.phpt b/Zend/tests/undefined_variables_operations.phpt similarity index 100% rename from Zend/tests/024.phpt rename to Zend/tests/undefined_variables_operations.phpt diff --git a/Zend/tests/019.phpt b/Zend/tests/unset_empty_isset_comprehensive.phpt similarity index 80% rename from Zend/tests/019.phpt rename to Zend/tests/unset_empty_isset_comprehensive.phpt index 4bc9d6be530cd..9a1aad99aa694 100644 --- a/Zend/tests/019.phpt +++ b/Zend/tests/unset_empty_isset_comprehensive.phpt @@ -703,12 +703,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -730,12 +736,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -757,12 +769,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -784,12 +802,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -817,12 +841,18 @@ array(3) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(3) { [1]=> @@ -841,12 +871,18 @@ array(2) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(2) { [2]=> @@ -861,12 +897,18 @@ array(1) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(1) { [3]=> @@ -877,12 +919,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -908,12 +956,18 @@ array(2) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(2) { [1]=> @@ -928,12 +982,18 @@ array(1) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(1) { [2]=> @@ -944,12 +1004,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -973,12 +1039,18 @@ array(1) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(1) { [2]=> @@ -989,12 +1061,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -1018,12 +1096,18 @@ array(1) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(1) { ["Age"]=> @@ -1034,12 +1118,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -1069,12 +1159,18 @@ array(4) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(4) { [1]=> @@ -1097,12 +1193,18 @@ array(3) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(3) { ["One"]=> @@ -1121,12 +1223,18 @@ array(2) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(2) { [2]=> @@ -1141,12 +1249,18 @@ array(1) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(1) { [""]=> @@ -1157,12 +1271,18 @@ array(0) { } Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(false) Warning: Undefined variable $key_val in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d bool(true) array(0) { } @@ -1175,11 +1295,11 @@ bool(true) *** Testing unset(), empty() & isset() with resource variables *** -- Iteration 1 -- -resource(%d) of type (stream) +resource(5) of type (stream) bool(true) bool(false) bool(true) -resource(%d) of type (stream) +resource(5) of type (stream) bool(false) bool(true) bool(false) @@ -1188,11 +1308,11 @@ bool(false) Warning: Undefined variable $resource in %s on line %d NULL -- Iteration 2 -- -resource(%d) of type (stream) +resource(6) of type (stream) bool(true) bool(false) bool(true) -resource(%d) of type (stream) +resource(6) of type (stream) bool(false) bool(true) bool(false) @@ -1207,7 +1327,7 @@ bool(false) bool(true) *** Testing unset(), empty() & isset() with objects *** -object(Point)#%d (3) { +object(Point)#1 (3) { ["x"]=> int(30) ["y"]=> @@ -1229,7 +1349,7 @@ bool(false) Warning: Undefined variable $lable in %s on line %d bool(true) -object(Point)#%d (3) { +object(Point)#1 (3) { ["x"]=> int(30) ["y"]=> @@ -1237,7 +1357,7 @@ object(Point)#%d (3) { ["lable"]=> string(6) "Point1" } -object(Point)#%d (2) { +object(Point)#1 (2) { ["y"]=> int(40) ["lable"]=> @@ -1245,7 +1365,7 @@ object(Point)#%d (2) { } bool(false) bool(true) -object(Point)#%d (0) { +object(Point)#1 (0) { } bool(true) bool(false) @@ -1266,7 +1386,7 @@ array(3) { [2]=> string(9) "testPoint" } -object(Point)#%d (3) { +object(Point)#1 (3) { ["x"]=> int(5) ["y"]=> diff --git a/Zend/tests/zend_ini/oss_fuzz_428983568.phpt b/Zend/tests/zend_ini/oss_fuzz_428983568.phpt new file mode 100644 index 0000000000000..80310fbd9287f --- /dev/null +++ b/Zend/tests/zend_ini/oss_fuzz_428983568.phpt @@ -0,0 +1,14 @@ +--TEST-- +OSS-Fuzz #428983568 +--FILE-- + +--EXPECTF-- +Warning: syntax error, unexpected end of file, expecting '}' in Unknown on line 1 + in %s on line %d +bool(false) diff --git a/Zend/zend.c b/Zend/zend.c index 2d8a0f455f8b4..045d25134f8c9 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1275,9 +1275,10 @@ ZEND_API size_t zend_get_page_size(void) SYSTEM_INFO system_info; GetSystemInfo(&system_info); return system_info.dwPageSize; -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__APPLE__) /* This returns the value obtained from - * the auxv vector, avoiding a syscall. */ + * the auxv vector, avoiding a + * syscall (on FreeBSD)/function call (on macOS). */ return getpagesize(); #else return (size_t) sysconf(_SC_PAGESIZE); @@ -1452,6 +1453,29 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( return; } + /* Emit any delayed error before handling fatal error */ + if ((type & E_FATAL_ERRORS) && !(type & E_DONT_BAIL) && EG(num_errors)) { + uint32_t num_errors = EG(num_errors); + zend_error_info **errors = EG(errors); + EG(num_errors) = 0; + EG(errors) = NULL; + + bool orig_record_errors = EG(record_errors); + EG(record_errors) = false; + + /* Disable user error handler before emitting delayed errors, as + * it's unsafe to execute user code after a fatal error. */ + int orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting); + EG(user_error_handler_error_reporting) = 0; + + zend_emit_recorded_errors_ex(num_errors, errors); + + EG(user_error_handler_error_reporting) = orig_user_error_handler_error_reporting; + EG(record_errors) = orig_record_errors; + EG(num_errors) = num_errors; + EG(errors) = errors; + } + if (EG(record_errors)) { zend_error_info *info = emalloc(sizeof(zend_error_info)); info->type = type; @@ -1464,6 +1488,11 @@ ZEND_API ZEND_COLD void zend_error_zstr_at( EG(num_errors)++; EG(errors) = erealloc(EG(errors), sizeof(zend_error_info*) * EG(num_errors)); EG(errors)[EG(num_errors)-1] = info; + + /* Do not process non-fatal recorded error */ + if (!(type & E_FATAL_ERRORS) || (type & E_DONT_BAIL)) { + return; + } } // Always clear the last backtrace. @@ -1752,15 +1781,20 @@ ZEND_API void zend_begin_record_errors(void) EG(errors) = NULL; } -ZEND_API void zend_emit_recorded_errors(void) +ZEND_API void zend_emit_recorded_errors_ex(uint32_t num_errors, zend_error_info **errors) { - EG(record_errors) = false; - for (uint32_t i = 0; i < EG(num_errors); i++) { - zend_error_info *error = EG(errors)[i]; + for (uint32_t i = 0; i < num_errors; i++) { + zend_error_info *error = errors[i]; zend_error_zstr_at(error->type, error->filename, error->lineno, error->message); } } +ZEND_API void zend_emit_recorded_errors(void) +{ + EG(record_errors) = false; + zend_emit_recorded_errors_ex(EG(num_errors), EG(errors)); +} + ZEND_API void zend_free_recorded_errors(void) { if (!EG(num_errors)) { diff --git a/Zend/zend.h b/Zend/zend.h index 0cf1faeb653fe..b103faf5ab59f 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -444,6 +444,7 @@ ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, ZEND_API void zend_restore_error_handling(zend_error_handling *saved); ZEND_API void zend_begin_record_errors(void); ZEND_API void zend_emit_recorded_errors(void); +ZEND_API void zend_emit_recorded_errors_ex(uint32_t num_errors, zend_error_info **errors); ZEND_API void zend_free_recorded_errors(void); END_EXTERN_C() diff --git a/Zend/zend_API.c b/Zend/zend_API.c index df8b4252c42ad..865a684e4e240 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1400,13 +1400,14 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ { zend_object *zobj = Z_OBJ_P(obj); zend_object_write_property_t write_property = zobj->handlers->write_property; - zend_class_entry *old_scope = EG(fake_scope); zend_string *key; zval *value; if (HT_IS_PACKED(properties)) { return; } + + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = Z_OBJCE_P(obj); ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, value) { if (key) { @@ -1519,6 +1520,9 @@ ZEND_API zend_result zend_update_class_constant(zend_class_constant *c, const ze zval_ptr_dtor(&c->value); ZVAL_COPY_VALUE(&c->value, &tmp); + /* may not return SUCCESS in case of an exception, + * should've returned FAILURE in zval_update_constant_ex! */ + ZEND_ASSERT(!EG(exception)); return SUCCESS; } @@ -1746,7 +1750,7 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties) size_t prop_name_len; if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) { zend_string *pname = zend_string_init(prop_name, prop_name_len, 0); - zend_class_entry *prev_scope = EG(fake_scope); + const zend_class_entry *prev_scope = EG(fake_scope); if (class_name && class_name[0] != '*') { zend_string *cname = zend_string_init(class_name, strlen(class_name), 0); EG(fake_scope) = zend_lookup_class(cname); @@ -1765,6 +1769,14 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties) property_info && (property_info->flags & ZEND_ACC_STATIC) == 0) { zval *slot = OBJ_PROP(object, property_info->offset); + if (UNEXPECTED((property_info->flags & ZEND_ACC_READONLY) && !Z_ISUNDEF_P(slot))) { + if (Z_PROP_FLAG_P(slot) & IS_PROP_REINITABLE) { + Z_PROP_FLAG_P(slot) &= ~IS_PROP_REINITABLE; + } else { + zend_readonly_property_modification_error(property_info); + return; + } + } zval_ptr_dtor(slot); ZVAL_COPY_VALUE(slot, prop); zval_add_ref(slot); @@ -3691,77 +3703,6 @@ ZEND_API void zend_disable_functions(const char *function_list) /* {{{ */ } /* }}} */ -#ifdef ZEND_WIN32 -#pragma optimize("", off) -#endif -static ZEND_COLD zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */ -{ - zend_object *intern; - - intern = zend_objects_new(class_type); - - /* Initialize default properties */ - if (EXPECTED(class_type->default_properties_count != 0)) { - zval *p = intern->properties_table; - zval *end = p + class_type->default_properties_count; - do { - ZVAL_UNDEF(p); - p++; - } while (p != end); - } - - zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name)); - return intern; -} -#ifdef ZEND_WIN32 -#pragma optimize("", on) -#endif -/* }}} */ - -static const zend_function_entry disabled_class_new[] = { - ZEND_FE_END -}; - -ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length) /* {{{ */ -{ - zend_class_entry *disabled_class; - zend_string *key; - zend_function *fn; - zend_property_info *prop; - - key = zend_string_alloc(class_name_length, 0); - zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length); - disabled_class = zend_hash_find_ptr(CG(class_table), key); - zend_string_release_ex(key, 0); - if (!disabled_class) { - return FAILURE; - } - - /* Will be reset by INIT_CLASS_ENTRY. */ - free(disabled_class->interfaces); - - INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new); - disabled_class->create_object = display_disabled_class; - - ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->function_table, fn) { - if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) && - fn->common.scope == disabled_class) { - zend_free_internal_arg_info(&fn->internal_function); - } - } ZEND_HASH_FOREACH_END(); - zend_hash_clean(&disabled_class->function_table); - ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->properties_info, prop) { - if (prop->ce == disabled_class) { - zend_string_release(prop->name); - zend_type_release(prop->type, /* persistent */ 1); - free(prop); - } - } ZEND_HASH_FOREACH_END(); - zend_hash_clean(&disabled_class->properties_info); - return SUCCESS; -} -/* }}} */ - static zend_always_inline zend_class_entry *get_scope(zend_execute_data *frame) { return frame && frame->func ? frame->func->common.scope : NULL; @@ -3769,7 +3710,7 @@ static zend_always_inline zend_class_entry *get_scope(zend_execute_data *frame) static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool *strict_class, char **error, bool suppress_deprecation) /* {{{ */ { - bool ret = 0; + bool ret = false; zend_class_entry *ce; size_t name_len = ZSTR_LEN(name); zend_string *lcname; @@ -3794,7 +3735,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc if (!fcc->object) { fcc->object = zend_get_this_object(frame); } - ret = 1; + ret = true; } } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_PARENT))) { if (!scope) { @@ -3814,7 +3755,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc fcc->object = zend_get_this_object(frame); } *strict_class = 1; - ret = 1; + ret = true; } } else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_STATIC))) { zend_class_entry *called_scope = zend_get_called_scope(frame); @@ -3831,7 +3772,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc fcc->object = zend_get_this_object(frame); } *strict_class = 1; - ret = 1; + ret = true; } } else if ((ce = zend_lookup_class(name)) != NULL) { zend_class_entry *scope = get_scope(frame); @@ -3851,7 +3792,7 @@ static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *sc fcc->called_scope = fcc->object ? fcc->object->ce : ce; } *strict_class = 1; - ret = 1; + ret = true; } else { if (error) zend_spprintf(error, 0, "class \"%.*s\" not found", (int)name_len, ZSTR_VAL(name)); } @@ -4021,13 +3962,11 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ ((fcc->object && fcc->calling_scope->__call) || (!fcc->object && fcc->calling_scope->__callstatic)))) { scope = get_scope(frame); - if (fcc->function_handler->common.scope != scope) { - if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE) - || !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) { - retval = 0; - fcc->function_handler = NULL; - goto get_function_via_handler; - } + ZEND_ASSERT(!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(fcc->function_handler, scope)) { + retval = 0; + fcc->function_handler = NULL; + goto get_function_via_handler; } } } else { @@ -4086,17 +4025,15 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_ if (retval && !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)) { scope = get_scope(frame); - if (fcc->function_handler->common.scope != scope) { - if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE) - || (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) { - if (error) { - if (*error) { - efree(*error); - } - zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); + ZEND_ASSERT(!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(fcc->function_handler, scope)) { + if (error) { + if (*error) { + efree(*error); } - retval = 0; + zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); } + retval = 0; } } } @@ -4160,13 +4097,10 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *obj if (ce == zend_ce_closure) { const zend_function *fn = zend_get_closure_method_def(Z_OBJ_P(callable)); - if (fn->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { - if (fn->common.scope) { - return zend_create_member_string(fn->common.scope->name, fn->common.function_name); - } else { - return zend_string_copy(fn->common.function_name); - } + if ((fn->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) && fn->common.scope) { + return zend_create_member_string(fn->common.scope->name, fn->common.function_name); } + return zend_string_copy(fn->common.function_name); } return zend_string_concat2( @@ -5006,9 +4940,9 @@ ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const cha } /* }}} */ -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_ex(const zend_class_entry *scope, zend_object *object, zend_string *name, zval *value) /* {{{ */ { - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; @@ -5018,10 +4952,10 @@ ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *obje } /* }}} */ -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(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value) /* {{{ */ { zend_string *property; - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; @@ -5033,7 +4967,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, } /* }}} */ -ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */ +ZEND_API void zend_update_property_null(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */ { zval tmp; @@ -5042,10 +4976,10 @@ ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *ob } /* }}} */ -ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */ +ZEND_API void zend_unset_property(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */ { zend_string *property; - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; @@ -5057,7 +4991,7 @@ ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, } /* }}} */ -ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */ +ZEND_API void zend_update_property_bool(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */ { zval tmp; @@ -5066,7 +5000,7 @@ ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *ob } /* }}} */ -ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */ +ZEND_API void zend_update_property_long(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */ { zval tmp; @@ -5075,7 +5009,7 @@ ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *ob } /* }}} */ -ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value) /* {{{ */ +ZEND_API void zend_update_property_double(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value) /* {{{ */ { zval tmp; @@ -5084,7 +5018,7 @@ ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object * } /* }}} */ -ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value) /* {{{ */ +ZEND_API void zend_update_property_str(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value) /* {{{ */ { zval tmp; @@ -5093,7 +5027,7 @@ ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *obj } /* }}} */ -ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value) /* {{{ */ +ZEND_API void zend_update_property_string(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value) /* {{{ */ { zval tmp; @@ -5103,7 +5037,7 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object * } /* }}} */ -ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */ +ZEND_API void zend_update_property_stringl(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */ { zval tmp; @@ -5117,7 +5051,6 @@ ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zen { zval *property, tmp; zend_property_info *prop_info; - zend_class_entry *old_scope = EG(fake_scope); if (UNEXPECTED(!(scope->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) { if (UNEXPECTED(zend_update_class_constants(scope) != SUCCESS)) { @@ -5125,6 +5058,7 @@ ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zen } } + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; property = zend_std_get_static_property_with_info(scope, name, BP_VAR_W, &prop_info); EG(fake_scope) = old_scope; @@ -5217,7 +5151,7 @@ ZEND_API zend_result zend_update_static_property_stringl(zend_class_entry *scope ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv) /* {{{ */ { zval *value; - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; @@ -5243,7 +5177,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, bool silent) /* {{{ */ { zval *property; - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = scope; property = zend_std_get_static_property(scope, name, silent ? BP_VAR_IS : BP_VAR_R); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 02ec1b18a6b69..f4a6fc5f50e9d 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -405,7 +405,6 @@ static zend_always_inline zend_result zend_register_class_alias(const char *name zend_register_class_alias_ex(ZEND_NS_NAME(ns, name), sizeof(ZEND_NS_NAME(ns, name))-1, ce, 1) 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); @@ -494,16 +493,16 @@ static zend_always_inline HashTable *zend_class_backed_enum_table(zend_class_ent } } -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); -ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value); -ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value); -ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value); -ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value); -ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value); -ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_length); -ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length); +ZEND_API void zend_update_property_ex(const zend_class_entry *scope, zend_object *object, zend_string *name, zval *value); +ZEND_API void zend_update_property(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value); +ZEND_API void zend_update_property_null(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length); +ZEND_API void zend_update_property_bool(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value); +ZEND_API void zend_update_property_long(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value); +ZEND_API void zend_update_property_double(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value); +ZEND_API void zend_update_property_str(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value); +ZEND_API void zend_update_property_string(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value); +ZEND_API void zend_update_property_stringl(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_length); +ZEND_API void zend_unset_property(const zend_class_entry *scope, zend_object *object, const char *name, size_t name_length); ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value); ZEND_API zend_result zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value); @@ -696,8 +695,8 @@ ZEND_API zend_result _call_user_function_impl(zval *object, zval *function_name, # define empty_fcall_info (zend_fcall_info) {0} # define empty_fcall_info_cache (zend_fcall_info_cache) {0} #else -# define empty_fcall_info zend_fcall_info {0} -# define empty_fcall_info_cache zend_fcall_info_cache {0} +# define empty_fcall_info zend_fcall_info {} +# define empty_fcall_info_cache zend_fcall_info_cache {} #endif /** Build zend_call_info/cache from a zval* @@ -2326,7 +2325,7 @@ static zend_always_inline bool zend_parse_arg_string(zval *arg, char **dest, siz static zend_always_inline bool zend_parse_arg_path_str(zval *arg, zend_string **dest, bool check_null, uint32_t arg_num) { if (!zend_parse_arg_str(arg, dest, check_null, arg_num) || - (*dest && UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(*dest), ZSTR_LEN(*dest))))) { + (*dest && UNEXPECTED(zend_str_has_nul_byte(*dest)))) { return 0; } return 1; diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index f2f801db63396..f3dfe0f9df57a 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -317,7 +317,9 @@ struct _zend_mm_heap { } debug; }; #endif +#if ZEND_DEBUG pid_t pid; +#endif zend_random_bytes_insecure_state rand_state; }; @@ -377,24 +379,6 @@ static const uint32_t bin_pages[] = { ZEND_MM_BINS_INFO(_BIN_DATA_PAGES, x, y) }; -#if ZEND_DEBUG -ZEND_COLD void zend_debug_alloc_output(char *format, ...) -{ - char output_buf[256]; - va_list args; - - va_start(args, format); - vsprintf(output_buf, format, args); - va_end(args); - -#ifdef ZEND_WIN32 - OutputDebugString(output_buf); -#else - fprintf(stderr, "%s", output_buf); -#endif -} -#endif - static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message) { fprintf(stderr, "%s\n", message); @@ -1310,15 +1294,20 @@ static zend_always_inline zend_mm_free_slot* zend_mm_encode_free_slot(const zend #endif } -static zend_always_inline zend_mm_free_slot* zend_mm_decode_free_slot(zend_mm_heap *heap, zend_mm_free_slot *slot) +static zend_always_inline zend_mm_free_slot* zend_mm_decode_free_slot_key(uintptr_t shadow_key, zend_mm_free_slot *slot) { #ifdef WORDS_BIGENDIAN - return (zend_mm_free_slot*)((uintptr_t)slot ^ heap->shadow_key); + return (zend_mm_free_slot*)((uintptr_t)slot ^ shadow_key); #else - return (zend_mm_free_slot*)(BSWAPPTR((uintptr_t)slot ^ heap->shadow_key)); + return (zend_mm_free_slot*)(BSWAPPTR((uintptr_t)slot ^ shadow_key)); #endif } +static zend_always_inline zend_mm_free_slot* zend_mm_decode_free_slot(zend_mm_heap *heap, zend_mm_free_slot *slot) +{ + return zend_mm_decode_free_slot_key(heap->shadow_key, slot); +} + static zend_always_inline void zend_mm_set_next_free_slot(zend_mm_heap *heap, uint32_t bin_num, zend_mm_free_slot *slot, zend_mm_free_slot *next) { ZEND_ASSERT(bin_data_size[bin_num] >= ZEND_MM_MIN_USEABLE_BIN_SIZE); @@ -2027,6 +2016,34 @@ static void zend_mm_init_key(zend_mm_heap *heap) zend_mm_refresh_key(heap); } +ZEND_API void zend_mm_refresh_key_child(zend_mm_heap *heap) +{ + uintptr_t old_key = heap->shadow_key; + + zend_mm_init_key(heap); + + /* Update shadow pointers with new key */ + for (int i = 0; i < ZEND_MM_BINS; i++) { + zend_mm_free_slot *slot = heap->free_slot[i]; + if (!slot) { + continue; + } + zend_mm_free_slot *next; + while ((next = slot->next_free_slot)) { + zend_mm_free_slot *shadow = ZEND_MM_FREE_SLOT_PTR_SHADOW(slot, i); + if (UNEXPECTED(next != zend_mm_decode_free_slot_key(old_key, shadow))) { + zend_mm_panic("zend_mm_heap corrupted"); + } + zend_mm_set_next_free_slot(heap, i, slot, next); + slot = next; + } + } + +#if ZEND_DEBUG + heap->pid = getpid(); +#endif +} + static zend_mm_heap *zend_mm_init(void) { zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc_int(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); @@ -2075,7 +2092,9 @@ static zend_mm_heap *zend_mm_init(void) heap->storage = NULL; #endif heap->huge_list = NULL; +#if ZEND_DEBUG heap->pid = getpid(); +#endif return heap; } @@ -2535,13 +2554,12 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) p->free_map[0] = (1L << ZEND_MM_FIRST_PAGE) - 1; p->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE); - pid_t pid = getpid(); - if (heap->pid != pid) { - zend_mm_init_key(heap); - heap->pid = pid; - } else { - zend_mm_refresh_key(heap); - } +#if ZEND_DEBUG + ZEND_ASSERT(getpid() == heap->pid + && "heap was re-used without calling zend_mm_refresh_key_child() after a fork"); +#endif + + zend_mm_refresh_key(heap); } } @@ -2949,6 +2967,11 @@ ZEND_API void shutdown_memory_manager(bool silent, bool full_shutdown) zend_mm_shutdown(AG(mm_heap), full_shutdown, silent); } +ZEND_API void refresh_memory_manager(void) +{ + zend_mm_refresh_key_child(AG(mm_heap)); +} + static ZEND_COLD ZEND_NORETURN void zend_out_of_memory(void) { fprintf(stderr, "Out of memory\n"); @@ -3506,7 +3529,9 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void memcpy(storage->data, data, data_size); } heap->storage = storage; +#if ZEND_DEBUG heap->pid = getpid(); +#endif return heap; #else return NULL; diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 541989a2a13e0..264e13848d1b7 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -220,6 +220,7 @@ ZEND_API bool zend_alloc_in_memory_limit_error_reporting(void); ZEND_API void start_memory_manager(void); ZEND_API void shutdown_memory_manager(bool silent, bool full_shutdown); +ZEND_API void refresh_memory_manager(void); ZEND_API bool is_zend_mm(void); ZEND_API bool is_zend_ptr(const void *ptr); @@ -316,6 +317,8 @@ struct _zend_mm_storage { ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap); ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void *data, size_t data_size); +ZEND_API void zend_mm_refresh_key_child(zend_mm_heap *heap); + /* // The following example shows how to use zend_mm_heap API with custom storage diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 728695bd9e930..9cb3c7aae4a1f 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -33,7 +33,7 @@ static inline void *zend_ast_alloc(size_t size) { return zend_arena_alloc(&CG(ast_arena), size); } -static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) { +static inline void *zend_ast_realloc(const void *old, size_t old_size, size_t new_size) { void *new = zend_ast_alloc(new_size); memcpy(new, old, old_size); return new; @@ -43,7 +43,7 @@ static inline size_t zend_ast_list_size(uint32_t children) { return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children; } -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) { +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(const znode *node) { zend_ast_znode *ast; ast = zend_ast_alloc(sizeof(zend_ast_znode)); @@ -66,7 +66,7 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc(void) { return (zend_ast *) ast; } -static zend_always_inline zend_ast * zend_ast_create_zval_int(zval *zv, uint32_t attr, uint32_t lineno) { +static zend_always_inline zend_ast * zend_ast_create_zval_int(const zval *zv, uint32_t attr, uint32_t lineno) { zend_ast_zval *ast; ast = zend_ast_alloc(sizeof(zend_ast_zval)); @@ -77,15 +77,15 @@ static zend_always_inline zend_ast * zend_ast_create_zval_int(zval *zv, uint32_t return (zend_ast *) ast; } -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno) { +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(const zval *zv, uint32_t lineno) { return zend_ast_create_zval_int(zv, 0, lineno); } -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) { +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(const zval *zv, zend_ast_attr attr) { return zend_ast_create_zval_int(zv, attr, CG(zend_lineno)); } -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv) { +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(const zval *zv) { return zend_ast_create_zval_int(zv, 0, CG(zend_lineno)); } @@ -498,7 +498,7 @@ static inline bool is_power_of_two(uint32_t n) { return ((n != 0) && (n == (n & (~n + 1)))); } -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) { +ZEND_ATTRIBUTE_NODISCARD ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) { zend_ast_list *list = zend_ast_get_list(ast); if (list->children >= 4 && is_power_of_two(list->children)) { list = zend_ast_realloc(list, @@ -508,7 +508,7 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) return (zend_ast *) list; } -static zend_result zend_ast_add_array_element(zval *result, zval *offset, zval *expr) +static zend_result zend_ast_add_array_element(const zval *result, zval *offset, zval *expr) { if (Z_TYPE_P(offset) == IS_UNDEF) { if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) { @@ -528,9 +528,9 @@ static zend_result zend_ast_add_array_element(zval *result, zval *offset, zval * return SUCCESS; } -static zend_result zend_ast_add_unpacked_element(zval *result, zval *expr) { +static zend_result zend_ast_add_unpacked_element(const zval *result, const zval *expr) { if (EXPECTED(Z_TYPE_P(expr) == IS_ARRAY)) { - HashTable *ht = Z_ARRVAL_P(expr); + const HashTable *ht = Z_ARRVAL_P(expr); zval *val; zend_string *key; @@ -610,9 +610,10 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( ret = FAILURE; } else { binary_op_type op = get_binary_op(ast->attr); - ret = op(result, &op1, &op2); + op(result, &op1, &op2); zval_ptr_dtor_nogc(&op1); zval_ptr_dtor_nogc(&op2); + ret = EG(exception) ? FAILURE : SUCCESS; } break; case ZEND_AST_GREATER: @@ -1054,6 +1055,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( case ZEND_AST_STATIC_CALL: { zend_function *fptr; + zend_class_entry *called_scope = NULL; switch (ast->kind) { case ZEND_AST_CALL: { ZEND_ASSERT(ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT); @@ -1085,34 +1087,29 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( ZEND_ASSERT(ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT); zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast->child[2]; + zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope); + if (!ce) { + return FAILURE; + } + called_scope = ce; + fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr); if (!fptr) { - zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope); - if (!ce) { - return FAILURE; - } zend_string *method_name = zend_ast_get_str(ast->child[1]); if (ce->get_static_method) { fptr = ce->get_static_method(ce, method_name); } else { fptr = zend_hash_find_ptr_lc(&ce->function_table, method_name); if (fptr) { - if (!(fptr->common.fn_flags & ZEND_ACC_PUBLIC)) { - if (UNEXPECTED(fptr->common.scope != scope)) { - if ( - UNEXPECTED(fptr->op_array.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fptr), scope)) - ) { - if (ce->__callstatic) { - zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions"); - } else { - zend_bad_method_call(fptr, method_name, scope); - } - - return FAILURE; - } + if (!zend_check_method_accessible(fptr, scope)) { + if (ce->__callstatic) { + zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions"); + } else { + zend_bad_method_call(fptr, method_name, scope); } + + return FAILURE; } } else { if (ce->__callstatic) { @@ -1151,7 +1148,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( } } - zend_create_fake_closure(result, fptr, scope, scope, NULL); + zend_create_fake_closure(result, fptr, fptr->common.scope, called_scope, NULL); return SUCCESS; } @@ -1249,7 +1246,7 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast) size = sizeof(zend_ast_fcc); } else if (zend_ast_is_list(ast)) { uint32_t i; - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); size = zend_ast_list_size(list->children); for (i = 0; i < list->children; i++) { @@ -1290,7 +1287,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf) Z_LINENO(new->val) = zend_ast_get_lineno(ast); buf = (void*)((char*)buf + sizeof(zend_ast_zval)); } else if (zend_ast_is_list(ast)) { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); zend_ast_list *new = (zend_ast_list*)buf; uint32_t i; new->kind = list->kind; @@ -1307,7 +1304,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf) } } } else if (ast->kind == ZEND_AST_OP_ARRAY) { - zend_ast_op_array *old = zend_ast_get_op_array(ast); + const zend_ast_op_array *old = zend_ast_get_op_array(ast); zend_ast_op_array *new = (zend_ast_op_array*)buf; new->kind = old->kind; new->attr = old->attr; @@ -1316,7 +1313,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf) function_add_ref((zend_function *)new->op_array); buf = (void*)((char*)buf + sizeof(zend_ast_op_array)); } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) { - zend_ast_fcc *old = (zend_ast_fcc*)ast; + const zend_ast_fcc *old = (zend_ast_fcc*)ast; zend_ast_fcc *new = (zend_ast_fcc*)buf; new->kind = old->kind; new->attr = old->attr; @@ -1377,7 +1374,7 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast) } else if (EXPECTED(ast->kind == ZEND_AST_ZVAL)) { zval_ptr_dtor_nogc(zend_ast_get_zval(ast)); } else if (EXPECTED(zend_ast_is_list(ast))) { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); if (list->children) { uint32_t i; @@ -1392,7 +1389,7 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast) } else if (EXPECTED(ast->kind == ZEND_AST_OP_ARRAY)) { destroy_op_array(zend_ast_get_op_array(ast)->op_array); } else if (EXPECTED(zend_ast_is_decl(ast))) { - zend_ast_decl *decl = (zend_ast_decl *) ast; + const zend_ast_decl *decl = (const zend_ast_decl *) ast; if (decl->name) { zend_string_release_ex(decl->name, 0); @@ -1471,7 +1468,7 @@ ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *contex static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent); -static ZEND_COLD void zend_ast_export_str(smart_str *str, zend_string *s) +static ZEND_COLD void zend_ast_export_str(smart_str *str, const zend_string *s) { size_t i; @@ -1486,7 +1483,7 @@ static ZEND_COLD void zend_ast_export_str(smart_str *str, zend_string *s) } } -static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s) +static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, const zend_string *s) { size_t i; @@ -1542,7 +1539,7 @@ static ZEND_COLD void zend_ast_export_indent(smart_str *str, int indent) static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent) { if (ast->kind == ZEND_AST_ZVAL) { - zval *zv = zend_ast_get_zval(ast); + const zval *zv = zend_ast_get_zval(ast); if (Z_TYPE_P(zv) == IS_STRING) { smart_str_append(str, Z_STR_P(zv)); @@ -1555,7 +1552,7 @@ static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int pr static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent) { if (ast->kind == ZEND_AST_ZVAL) { - zval *zv = zend_ast_get_zval(ast); + const zval *zv = zend_ast_get_zval(ast); if (Z_TYPE_P(zv) == IS_STRING) { if (ast->attr == ZEND_NAME_FQ) { @@ -1634,7 +1631,7 @@ static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int pri /* Use zend_ast_export_list() unless fewer than `list->children` children should * be exported. */ -static ZEND_COLD void zend_ast_export_list_ex(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent, int children) +static ZEND_COLD void zend_ast_export_list_ex(smart_str *str, const zend_ast_list *list, bool separator, int priority, int indent, uint32_t children) { ZEND_ASSERT(children <= list->children); uint32_t i = 0; @@ -1648,12 +1645,12 @@ static ZEND_COLD void zend_ast_export_list_ex(smart_str *str, zend_ast_list *lis } } -static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent) +static ZEND_COLD void zend_ast_export_list(smart_str *str, const zend_ast_list *list, bool separator, int priority, int indent) { zend_ast_export_list_ex(str, list, separator, priority, indent, list->children); } -static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent) +static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, const zend_ast_list *list, int indent) { uint32_t i = 0; zend_ast *ast; @@ -1661,7 +1658,7 @@ static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, ze while (i < list->children) { ast = list->child[i]; if (ast->kind == ZEND_AST_ZVAL) { - zval *zv = zend_ast_get_zval(ast); + const zval *zv = zend_ast_get_zval(ast); ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); zend_ast_export_qstr(str, quote, Z_STR_P(zv)); @@ -1682,7 +1679,7 @@ static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, ze } } -static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, zend_ast_list *list, int indent, const char *separator) +static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, const zend_ast_list *list, int indent, const char *separator) { uint32_t i = 0; @@ -1698,7 +1695,7 @@ static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, zend_ast_list #define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ") #define zend_ast_export_catch_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, "|") -static ZEND_COLD void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent) +static ZEND_COLD void zend_ast_export_var_list(smart_str *str, const zend_ast_list *list, int indent) { uint32_t i = 0; @@ -1723,7 +1720,7 @@ static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int in if (ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) { - zend_ast_list *list = (zend_ast_list*)ast; + const zend_ast_list *list = (const zend_ast_list*)ast; uint32_t i = 0; while (i < list->children) { @@ -1750,8 +1747,8 @@ static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int in case ZEND_AST_DECLARE: break; case ZEND_AST_PROP_GROUP: { - zend_ast *first_prop = zend_ast_get_list(ast->child[1])->child[0]; - zend_ast *hook_list = first_prop->child[3]; + const zend_ast *first_prop = zend_ast_get_list(ast->child[1])->child[0]; + const zend_ast *hook_list = first_prop->child[3]; if (hook_list == NULL) { smart_str_appendc(str, ';'); } @@ -1765,7 +1762,7 @@ static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int in } } -static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent) +static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, const zend_ast_list *list, int indent) { uint32_t i; zend_ast *ast; @@ -1789,7 +1786,7 @@ static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *lis zend_ast_export_indent(str, indent); smart_str_appends(str, "} else "); if (ast->child[1] && ast->child[1]->kind == ZEND_AST_IF) { - list = (zend_ast_list*)ast->child[1]; + list = (const zend_ast_list*)ast->child[1]; goto tail_call; } else { smart_str_appends(str, "{\n"); @@ -1802,7 +1799,7 @@ static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *lis smart_str_appendc(str, '}'); } -static ZEND_COLD void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent) +static ZEND_COLD void zend_ast_export_zval(smart_str *str, const zval *zv, int priority, int indent) { ZVAL_DEREF(zv); switch (Z_TYPE_P(zv)) { @@ -1859,7 +1856,7 @@ static ZEND_COLD void zend_ast_export_zval(smart_str *str, zval *zv, int priorit } } -static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) { +static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, const zend_ast_decl *decl, int indent) { if (decl->child[0]) { smart_str_appends(str, " extends "); zend_ast_export_ns_name(str, decl->child[0], 0, indent); @@ -1875,9 +1872,9 @@ static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_d } static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast *ast, int indent) { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); for (uint32_t i = 0; i < list->children; i++) { - zend_ast *attr = list->child[i]; + const zend_ast *attr = list->child[i]; if (i) { smart_str_appends(str, ", "); @@ -1893,7 +1890,7 @@ static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast * } static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, bool newlines) { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; for (i = 0; i < list->children; i++) { @@ -1932,7 +1929,7 @@ static ZEND_COLD void zend_ast_export_visibility(smart_str *str, uint32_t flags, static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) { if (ast->kind == ZEND_AST_TYPE_UNION) { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); for (uint32_t i = 0; i < list->children; i++) { if (i != 0) { smart_str_appendc(str, '|'); @@ -1942,7 +1939,7 @@ static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int in return; } if (ast->kind == ZEND_AST_TYPE_INTERSECTION) { - zend_ast_list *list = zend_ast_get_list(ast); + const zend_ast_list *list = zend_ast_get_list(ast); for (uint32_t i = 0; i < list->children; i++) { if (i != 0) { smart_str_appendc(str, '&'); @@ -1957,7 +1954,7 @@ static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int in zend_ast_export_ns_name(str, ast, 0, indent); } -static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, zend_ast_list *hook_list, int indent) +static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, const zend_ast_list *hook_list, int indent) { smart_str_appends(str, " {"); smart_str_appendc(str, '\n'); @@ -1965,7 +1962,7 @@ static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, zend_ast_list *h zend_ast_export_indent(str, indent); for (uint32_t i = 0; i < hook_list->children; i++) { - zend_ast_decl *hook = (zend_ast_decl *)hook_list->child[i]; + const zend_ast_decl *hook = (const zend_ast_decl *)hook_list->child[i]; zend_ast_export_visibility(str, hook->flags, ZEND_MODIFIER_TARGET_PROPERTY); if (hook->flags & ZEND_ACC_FINAL) { smart_str_appends(str, "final "); @@ -2039,7 +2036,7 @@ static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, zend_ast_list *h static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent) { - zend_ast_decl *decl; + const zend_ast_decl *decl; int p, pl, pr; const char *op; @@ -2075,7 +2072,10 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case ZEND_AST_CLOSURE: case ZEND_AST_ARROW_FUNC: case ZEND_AST_METHOD: - decl = (zend_ast_decl *) ast; + decl = (const zend_ast_decl *) ast; + if (decl->kind == ZEND_AST_ARROW_FUNC && (decl->attr & ZEND_PARENTHESIZED_ARROW_FUNC)) { + smart_str_appendc(str, '('); + } if (decl->child[4]) { bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC); zend_ast_export_attributes(str, decl->child[4], indent, newlines); @@ -2119,6 +2119,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio } smart_str_appends(str, " => "); zend_ast_export_ex(str, body, 0, indent); + if (decl->attr & ZEND_PARENTHESIZED_ARROW_FUNC) { + smart_str_appendc(str, ')'); + } break; } @@ -2134,7 +2137,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio } break; case ZEND_AST_CLASS: - decl = (zend_ast_decl *) ast; + decl = (const zend_ast_decl *) ast; if (decl->child[3]) { zend_ast_export_attributes(str, decl->child[3], indent, 1); } @@ -2170,16 +2173,16 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case ZEND_AST_EXPR_LIST: case ZEND_AST_PARAM_LIST: simple_list: - zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent); + zend_ast_export_list(str, zend_ast_get_list(ast), 1, 20, indent); break; case ZEND_AST_ARRAY: smart_str_appendc(str, '['); - zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent); + zend_ast_export_list(str, zend_ast_get_list(ast), 1, 20, indent); smart_str_appendc(str, ']'); break; case ZEND_AST_ENCAPS_LIST: smart_str_appendc(str, '"'); - zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent); + zend_ast_export_encaps_list(str, '"', zend_ast_get_list(ast), indent); smart_str_appendc(str, '"'); break; case ZEND_AST_STMT_LIST: @@ -2187,16 +2190,16 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio zend_ast_export_stmt(str, ast, indent); break; case ZEND_AST_IF: - zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent); + zend_ast_export_if_stmt(str, zend_ast_get_list(ast), indent); break; case ZEND_AST_SWITCH_LIST: case ZEND_AST_CATCH_LIST: case ZEND_AST_MATCH_ARM_LIST: - zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent); + zend_ast_export_list(str, zend_ast_get_list(ast), 0, 0, indent); break; case ZEND_AST_CLOSURE_USES: smart_str_appends(str, " use("); - zend_ast_export_var_list(str, (zend_ast_list*)ast, indent); + zend_ast_export_var_list(str, zend_ast_get_list(ast), indent); smart_str_appendc(str, ')'); break; case ZEND_AST_PROP_GROUP: { @@ -2261,7 +2264,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio goto simple_list; case ZEND_AST_NAME_LIST: - zend_ast_export_name_list(str, (zend_ast_list*)ast, indent); + zend_ast_export_name_list(str, zend_ast_get_list(ast), indent); break; case ZEND_AST_USE: smart_str_appends(str, "use "); @@ -2316,7 +2319,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case IS_NULL: PREFIX_OP("(unset)", 240, 241); case _IS_BOOL: PREFIX_OP("(bool)", 240, 241); case IS_LONG: PREFIX_OP("(int)", 240, 241); - case IS_DOUBLE: PREFIX_OP("(double)", 240, 241); + case IS_DOUBLE: PREFIX_OP("(float)", 240, 241); case IS_STRING: PREFIX_OP("(string)", 240, 241); case IS_ARRAY: PREFIX_OP("(array)", 240, 241); case IS_OBJECT: PREFIX_OP("(object)", 240, 241); @@ -2335,7 +2338,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case ZEND_AST_SHELL_EXEC: smart_str_appendc(str, '`'); if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) { - zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent); + zend_ast_export_encaps_list(str, '`', zend_ast_get_list(ast->child[0]), indent); } else { zval *zv; ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL); @@ -2529,7 +2532,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case ZEND_AST_NEW: smart_str_appends(str, "new "); if (ast->child[0]->kind == ZEND_AST_CLASS) { - zend_ast_decl *decl = (zend_ast_decl *) ast->child[0]; + const zend_ast_decl *decl = (const zend_ast_decl *) ast->child[0]; if (decl->child[3]) { zend_ast_export_attributes(str, decl->child[3], indent, 0); } @@ -2632,7 +2635,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case ZEND_AST_MATCH_ARM: zend_ast_export_indent(str, indent); if (ast->child[0]) { - zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent); + zend_ast_export_list(str, zend_ast_get_list(ast->child[0]), 1, 0, indent); smart_str_appends(str, " => "); } else { smart_str_appends(str, "default => "); @@ -2643,7 +2646,7 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio case ZEND_AST_DECLARE: smart_str_appends(str, "declare("); ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL); - zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent); + zend_ast_export_list(str, zend_ast_get_list(ast->child[0]), 1, 0, indent); smart_str_appendc(str, ')'); if (ast->child[1]) { smart_str_appends(str, " {\n"); @@ -2956,7 +2959,7 @@ zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr) /* Since constants are already stored in a list, just add the attributes * to that list instead of storing them elsewhere; * zend_compile_const_decl() checks the kind of the list elements. */ - zend_ast_list_add(ast, attr); + ast = zend_ast_list_add(ast, attr); break; EMPTY_SWITCH_DEFAULT_CASE() } diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 08400cff5dd8e..fb48b187252b3 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -220,7 +220,7 @@ typedef struct _zend_ast_op_array { /* Separate structure for function and class declaration, as they need extra information. */ typedef struct _zend_ast_decl { zend_ast_kind kind; - zend_ast_attr attr; /* Unused - for structure compatibility */ + zend_ast_attr attr; uint32_t start_lineno; uint32_t end_lineno; uint32_t flags; @@ -239,9 +239,9 @@ typedef struct _zend_ast_fcc { typedef void (*zend_ast_process_t)(zend_ast *ast); extern ZEND_API zend_ast_process_t zend_ast_process; -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno); -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr); -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv); +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(const zval *zv, uint32_t lineno); +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(const zval *zv, zend_ast_attr attr); +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(const zval *zv); ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str); ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval); @@ -320,7 +320,7 @@ ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, .. ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...); #endif -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *list, zend_ast *op); +ZEND_ATTRIBUTE_NODISCARD ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *list, zend_ast *op); ZEND_API zend_ast *zend_ast_create_decl( zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, @@ -348,15 +348,15 @@ static zend_always_inline size_t zend_ast_size(uint32_t children) { return XtOffsetOf(zend_ast, child) + (sizeof(zend_ast *) * children); } -static zend_always_inline bool zend_ast_is_special(zend_ast *ast) { +static zend_always_inline bool zend_ast_is_special(const zend_ast *ast) { return (ast->kind >> ZEND_AST_SPECIAL_SHIFT) & 1; } -static zend_always_inline bool zend_ast_is_decl(zend_ast *ast) { +static zend_always_inline bool zend_ast_is_decl(const zend_ast *ast) { return zend_ast_is_special(ast) && ast->kind >= ZEND_AST_FUNC_DECL; } -static zend_always_inline bool zend_ast_is_list(zend_ast *ast) { +static zend_always_inline bool zend_ast_is_list(const zend_ast *ast) { return (ast->kind >> ZEND_AST_IS_LIST_SHIFT) & 1; } static zend_always_inline zend_ast_list *zend_ast_get_list(zend_ast *ast) { @@ -369,7 +369,7 @@ static zend_always_inline zval *zend_ast_get_zval(zend_ast *ast) { return &((zend_ast_zval *) ast)->val; } static zend_always_inline zend_string *zend_ast_get_str(zend_ast *ast) { - zval *zv = zend_ast_get_zval(ast); + const zval *zv = zend_ast_get_zval(ast); ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); return Z_STR_P(zv); } @@ -385,7 +385,7 @@ static zend_always_inline zend_string *zend_ast_get_constant_name(zend_ast *ast) return Z_STR(((zend_ast_zval *) ast)->val); } -static zend_always_inline uint32_t zend_ast_get_num_children(zend_ast *ast) { +static zend_always_inline uint32_t zend_ast_get_num_children(const zend_ast *ast) { ZEND_ASSERT(!zend_ast_is_list(ast)); ZEND_ASSERT(!zend_ast_is_special(ast)); @@ -393,10 +393,10 @@ static zend_always_inline uint32_t zend_ast_get_num_children(zend_ast *ast) { } static zend_always_inline uint32_t zend_ast_get_lineno(zend_ast *ast) { if (ast->kind == ZEND_AST_ZVAL) { - zval *zv = zend_ast_get_zval(ast); + const zval *zv = zend_ast_get_zval(ast); return Z_LINENO_P(zv); } else if (ast->kind == ZEND_AST_CONSTANT) { - zval *zv = &((zend_ast_zval *) ast)->val; + const zval *zv = &((const zend_ast_zval *) ast)->val; return Z_LINENO_P(zv); } else { return ast->lineno; diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index c3633801be83e..b69e192701e48 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -32,6 +32,7 @@ ZEND_API zend_class_entry *zend_ce_sensitive_parameter_value; ZEND_API zend_class_entry *zend_ce_override; ZEND_API zend_class_entry *zend_ce_deprecated; ZEND_API zend_class_entry *zend_ce_nodiscard; +ZEND_API zend_class_entry *zend_ce_delayed_target_validation; static zend_object_handlers attributes_object_handlers_sensitive_parameter_value; @@ -69,30 +70,63 @@ uint32_t zend_attribute_attribute_get_flags(zend_attribute *attr, zend_class_ent return ZEND_ATTRIBUTE_TARGET_ALL; } -static void validate_allow_dynamic_properties( +static zend_string *validate_allow_dynamic_properties( zend_attribute *attr, uint32_t target, zend_class_entry *scope) { + ZEND_ASSERT(scope != NULL); + const char *msg = NULL; if (scope->ce_flags & ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to trait %s", - ZSTR_VAL(scope->name) - ); + msg = "Cannot apply #[\\AllowDynamicProperties] to trait %s"; + } else if (scope->ce_flags & ZEND_ACC_INTERFACE) { + msg = "Cannot apply #[\\AllowDynamicProperties] to interface %s"; + } else if (scope->ce_flags & ZEND_ACC_READONLY_CLASS) { + msg = "Cannot apply #[\\AllowDynamicProperties] to readonly class %s"; + } else if (scope->ce_flags & ZEND_ACC_ENUM) { + msg = "Cannot apply #[\\AllowDynamicProperties] to enum %s"; } - if (scope->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to interface %s", - ZSTR_VAL(scope->name) - ); + if (msg != NULL) { + return zend_strpprintf(0, msg, ZSTR_VAL(scope->name)); } - if (scope->ce_flags & ZEND_ACC_READONLY_CLASS) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to readonly class %s", - ZSTR_VAL(scope->name) - ); + scope->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; + return NULL; +} + +static zend_string *validate_attribute( + zend_attribute *attr, uint32_t target, zend_class_entry *scope) +{ + const char *msg = NULL; + if (scope->ce_flags & ZEND_ACC_TRAIT) { + msg = "Cannot apply #[\\Attribute] to trait %s"; + } else if (scope->ce_flags & ZEND_ACC_INTERFACE) { + msg = "Cannot apply #[\\Attribute] to interface %s"; + } else if (scope->ce_flags & ZEND_ACC_ENUM) { + msg = "Cannot apply #[\\Attribute] to enum %s"; + } else if (scope->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) { + msg = "Cannot apply #[\\Attribute] to abstract class %s"; } - if (scope->ce_flags & ZEND_ACC_ENUM) { - zend_error_noreturn(E_ERROR, "Cannot apply #[AllowDynamicProperties] to enum %s", - ZSTR_VAL(scope->name) - ); + if (msg != NULL) { + return zend_strpprintf(0, msg, ZSTR_VAL(scope->name)); } - scope->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; + return NULL; +} + +static zend_string *validate_deprecated( + zend_attribute *attr, + uint32_t target, + zend_class_entry *scope +) { + if (target != ZEND_ATTRIBUTE_TARGET_CLASS) { + /* Being used for a method or something, validation does not apply */ + return NULL; + } + if (!(scope->ce_flags & ZEND_ACC_TRAIT)) { + const char *type = zend_get_object_type_case(scope, false); + return zend_strpprintf(0, "Cannot apply #[\\Deprecated] to %s %s", type, ZSTR_VAL(scope->name)); + } + + scope->ce_flags |= ZEND_ACC_DEPRECATED; + return NULL; + } ZEND_METHOD(Attribute, __construct) @@ -194,6 +228,20 @@ ZEND_METHOD(Deprecated, __construct) } } +static zend_string *validate_nodiscard( + zend_attribute *attr, uint32_t target, zend_class_entry *scope) +{ + ZEND_ASSERT(CG(in_compilation)); + const zend_string *prop_info_name = CG(context).active_property_info_name; + if (prop_info_name != NULL) { + // Applied to a hook + return ZSTR_INIT_LITERAL("#[\\NoDiscard] is not supported for property hooks", 0); + } + zend_op_array *op_array = CG(active_op_array); + op_array->fn_flags |= ZEND_ACC_NODISCARD; + return NULL; +} + ZEND_METHOD(NoDiscard, __construct) { zend_string *message = NULL; @@ -421,6 +469,9 @@ static void attr_free(zval *v) zend_string_release(attr->name); zend_string_release(attr->lcname); + if (attr->validation_error != NULL) { + zend_string_release(attr->validation_error); + } for (uint32_t i = 0; i < attr->argc; i++) { if (attr->args[i].name) { @@ -453,6 +504,7 @@ ZEND_API zend_attribute *zend_add_attribute(HashTable **attributes, zend_string } attr->lcname = zend_string_tolower_ex(attr->name, persistent); + attr->validation_error = NULL; attr->flags = flags; attr->lineno = lineno; attr->offset = offset; @@ -522,6 +574,7 @@ void zend_register_attribute_ce(void) zend_ce_attribute = register_class_Attribute(); attr = zend_mark_internal_attribute(zend_ce_attribute); + attr->validator = validate_attribute; zend_ce_return_type_will_change_attribute = register_class_ReturnTypeWillChange(); zend_mark_internal_attribute(zend_ce_return_type_will_change_attribute); @@ -545,9 +598,14 @@ void zend_register_attribute_ce(void) zend_ce_deprecated = register_class_Deprecated(); attr = zend_mark_internal_attribute(zend_ce_deprecated); + attr->validator = validate_deprecated; zend_ce_nodiscard = register_class_NoDiscard(); attr = zend_mark_internal_attribute(zend_ce_nodiscard); + attr->validator = validate_nodiscard; + + zend_ce_delayed_target_validation = register_class_DelayedTargetValidation(); + attr = zend_mark_internal_attribute(zend_ce_delayed_target_validation); } void zend_attributes_shutdown(void) diff --git a/Zend/zend_attributes.h b/Zend/zend_attributes.h index a4d6b28c0094a..10227c2d1e8ef 100644 --- a/Zend/zend_attributes.h +++ b/Zend/zend_attributes.h @@ -50,6 +50,7 @@ extern ZEND_API zend_class_entry *zend_ce_sensitive_parameter_value; extern ZEND_API zend_class_entry *zend_ce_override; extern ZEND_API zend_class_entry *zend_ce_deprecated; extern ZEND_API zend_class_entry *zend_ce_nodiscard; +extern ZEND_API zend_class_entry *zend_ce_delayed_target_validation; typedef struct { zend_string *name; @@ -59,6 +60,9 @@ typedef struct { typedef struct _zend_attribute { zend_string *name; zend_string *lcname; + /* Only non-null for internal attributes with validation errors that are + * delayed until runtime via #[\DelayedTargetValidation] */ + zend_string *validation_error; uint32_t flags; uint32_t lineno; /* Parameter offsets start at 1, everything else uses 0. */ @@ -70,7 +74,7 @@ typedef struct _zend_attribute { typedef struct _zend_internal_attribute { zend_class_entry *ce; uint32_t flags; - void (*validator)(zend_attribute *attr, uint32_t target, zend_class_entry *scope); + zend_string* (*validator)(zend_attribute *attr, uint32_t target, zend_class_entry *scope); } zend_internal_attribute; ZEND_API zend_attribute *zend_get_attribute(HashTable *attributes, zend_string *lcname); diff --git a/Zend/zend_attributes.stub.php b/Zend/zend_attributes.stub.php index fe70de83e4d21..ded9c89593a36 100644 --- a/Zend/zend_attributes.stub.php +++ b/Zend/zend_attributes.stub.php @@ -68,7 +68,7 @@ public function __debugInfo(): array {} /** * @strict-properties */ -#[Attribute(Attribute::TARGET_METHOD)] +#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_PROPERTY)] final class Override { public function __construct() {} @@ -77,7 +77,7 @@ public function __construct() {} /** * @strict-properties */ -#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT|Attribute::TARGET_CONSTANT)] +#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT|Attribute::TARGET_CONSTANT|Attribute::TARGET_CLASS)] final class Deprecated { public readonly ?string $message; @@ -97,3 +97,9 @@ final class NoDiscard public function __construct(?string $message = null) {} } + +/** + * @strict-properties + */ +#[Attribute(Attribute::TARGET_ALL)] +final class DelayedTargetValidation {} diff --git a/Zend/zend_attributes_arginfo.h b/Zend/zend_attributes_arginfo.h index 14afe40c01adf..05f7eeb3e5d45 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: 9aee3d8f2ced376f5929048444eaa2529ff90311 */ + * Stub hash: b868cb33f41d9442f42d0cec84e33fcc09f5d88c */ 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") @@ -156,9 +156,7 @@ static zend_class_entry *register_class_Attribute(void) zend_string *attribute_name_Attribute_class_Attribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_Attribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Attribute_0, 1); zend_string_release(attribute_name_Attribute_class_Attribute_0); - zval attribute_Attribute_class_Attribute_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_Attribute_0_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); - ZVAL_COPY_VALUE(&attribute_Attribute_class_Attribute_0->args[0].value, &attribute_Attribute_class_Attribute_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_Attribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_CLASS); return class_entry; } @@ -173,9 +171,7 @@ static zend_class_entry *register_class_ReturnTypeWillChange(void) zend_string *attribute_name_Attribute_class_ReturnTypeWillChange_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_ReturnTypeWillChange_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ReturnTypeWillChange_0, 1); zend_string_release(attribute_name_Attribute_class_ReturnTypeWillChange_0); - zval attribute_Attribute_class_ReturnTypeWillChange_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_ReturnTypeWillChange_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ReturnTypeWillChange_0->args[0].value, &attribute_Attribute_class_ReturnTypeWillChange_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_ReturnTypeWillChange_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD); return class_entry; } @@ -190,9 +186,7 @@ static zend_class_entry *register_class_AllowDynamicProperties(void) zend_string *attribute_name_Attribute_class_AllowDynamicProperties_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_AllowDynamicProperties_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_AllowDynamicProperties_0, 1); zend_string_release(attribute_name_Attribute_class_AllowDynamicProperties_0); - zval attribute_Attribute_class_AllowDynamicProperties_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_AllowDynamicProperties_0_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); - ZVAL_COPY_VALUE(&attribute_Attribute_class_AllowDynamicProperties_0->args[0].value, &attribute_Attribute_class_AllowDynamicProperties_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_AllowDynamicProperties_0->args[0].value, ZEND_ATTRIBUTE_TARGET_CLASS); return class_entry; } @@ -207,9 +201,7 @@ static zend_class_entry *register_class_SensitiveParameter(void) zend_string *attribute_name_Attribute_class_SensitiveParameter_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_SensitiveParameter_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_SensitiveParameter_0, 1); zend_string_release(attribute_name_Attribute_class_SensitiveParameter_0); - zval attribute_Attribute_class_SensitiveParameter_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_SensitiveParameter_0_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); - ZVAL_COPY_VALUE(&attribute_Attribute_class_SensitiveParameter_0->args[0].value, &attribute_Attribute_class_SensitiveParameter_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_SensitiveParameter_0->args[0].value, ZEND_ATTRIBUTE_TARGET_PARAMETER); return class_entry; } @@ -238,9 +230,7 @@ static zend_class_entry *register_class_Override(void) zend_string *attribute_name_Attribute_class_Override_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_Override_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Override_0, 1); zend_string_release(attribute_name_Attribute_class_Override_0); - zval attribute_Attribute_class_Override_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_Override_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); - ZVAL_COPY_VALUE(&attribute_Attribute_class_Override_0->args[0].value, &attribute_Attribute_class_Override_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_Override_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_PROPERTY); return class_entry; } @@ -263,9 +253,7 @@ static zend_class_entry *register_class_Deprecated(void) zend_string *attribute_name_Attribute_class_Deprecated_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_Deprecated_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Deprecated_0, 1); zend_string_release(attribute_name_Attribute_class_Deprecated_0); - zval attribute_Attribute_class_Deprecated_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_Deprecated_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_CLASS_CONST | ZEND_ATTRIBUTE_TARGET_CONST); - ZVAL_COPY_VALUE(&attribute_Attribute_class_Deprecated_0->args[0].value, &attribute_Attribute_class_Deprecated_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_Deprecated_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION | ZEND_ATTRIBUTE_TARGET_CLASS_CONST | ZEND_ATTRIBUTE_TARGET_CONST | ZEND_ATTRIBUTE_TARGET_CLASS); return class_entry; } @@ -284,9 +272,22 @@ static zend_class_entry *register_class_NoDiscard(void) zend_string *attribute_name_Attribute_class_NoDiscard_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_NoDiscard_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_NoDiscard_0, 1); zend_string_release(attribute_name_Attribute_class_NoDiscard_0); - zval attribute_Attribute_class_NoDiscard_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_NoDiscard_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION); - ZVAL_COPY_VALUE(&attribute_Attribute_class_NoDiscard_0->args[0].value, &attribute_Attribute_class_NoDiscard_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_NoDiscard_0->args[0].value, ZEND_ATTRIBUTE_TARGET_METHOD | ZEND_ATTRIBUTE_TARGET_FUNCTION); + + return class_entry; +} + +static zend_class_entry *register_class_DelayedTargetValidation(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "DelayedTargetValidation", NULL); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES); + + zend_string *attribute_name_Attribute_class_DelayedTargetValidation_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_DelayedTargetValidation_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_DelayedTargetValidation_0, 1); + zend_string_release(attribute_name_Attribute_class_DelayedTargetValidation_0); + ZVAL_LONG(&attribute_Attribute_class_DelayedTargetValidation_0->args[0].value, ZEND_ATTRIBUTE_TARGET_ALL); return class_entry; } diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 48e5c70897294..fa2859ee4e9f1 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -72,9 +72,12 @@ zend_result zend_startup_builtin_functions(void) /* {{{ */ ZEND_FUNCTION(clone) { zend_object *zobj; + HashTable *with = (HashTable*)&zend_empty_array; - ZEND_PARSE_PARAMETERS_START(1, 1) + ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_OBJ(zobj) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT(with) ZEND_PARSE_PARAMETERS_END(); /* clone() also exists as the ZEND_CLONE OPcode and both implementations must be kept in sync. */ @@ -89,22 +92,22 @@ ZEND_FUNCTION(clone) RETURN_THROWS(); } - if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { - if (clone->common.scope != scope) { - if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_throw_error(NULL, "Call to %s %s::__clone() from %s%s", - zend_visibility_string(clone->common.fn_flags), ZSTR_VAL(clone->common.scope->name), - scope ? "scope " : "global scope", - scope ? ZSTR_VAL(scope->name) : "" - ); - RETURN_THROWS(); - } - } + if (clone && !zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + RETURN_THROWS(); } zend_object *cloned; - cloned = zobj->handlers->clone_obj(zobj); + if (zend_hash_num_elements(with) > 0) { + if (UNEXPECTED(!zobj->handlers->clone_obj_with)) { + zend_throw_error(NULL, "Cloning objects of class %s with updated properties is not supported", ZSTR_VAL(ce->name)); + RETURN_THROWS(); + } + + cloned = zobj->handlers->clone_obj_with(zobj, scope, with); + } else { + cloned = zobj->handlers->clone_obj(zobj); + } ZEND_ASSERT(cloned || EG(exception)); if (EXPECTED(cloned)) { @@ -592,7 +595,7 @@ ZEND_FUNCTION(define) /* non persistent */ ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); c.name = zend_string_copy(name); - if (zend_register_constant(&c) == SUCCESS) { + if (zend_register_constant(&c) != NULL) { RETURN_TRUE; } else { RETURN_FALSE; @@ -957,13 +960,7 @@ ZEND_FUNCTION(get_class_methods) scope = zend_get_executed_scope(); ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, mptr) { - if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) - || (scope && - (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && - zend_check_protected(mptr->common.scope, scope)) - || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && - scope == mptr->common.scope))) - ) { + if (zend_check_method_accessible(mptr, scope)) { ZVAL_STR_COPY(&method_name, mptr->common.function_name); zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name); } @@ -1486,15 +1483,15 @@ ZEND_FUNCTION(get_defined_functions) zval internal, user; zend_string *key; zend_function *func; - bool exclude_disabled = 1; + bool exclude_disabled = true; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &exclude_disabled) == FAILURE) { RETURN_THROWS(); } - if (exclude_disabled == 0) { + if (ZEND_NUM_ARGS() == 1) { zend_error(E_DEPRECATED, - "get_defined_functions(): Setting $exclude_disabled to false has no effect"); + "get_defined_functions(): The $exclude_disabled parameter has no effect since PHP 8.0"); } array_init(&internal); @@ -1994,8 +1991,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } stack_frame = zend_new_array(8); zend_hash_real_init_mixed(stack_frame); - zend_string *name = func->common.function_name; - ZVAL_STRINGL(&tmp, ZSTR_VAL(name), ZSTR_LEN(name)); + ZVAL_STR_COPY(&tmp, func->common.function_name); _zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1); /* Steal file and line from the previous frame. */ if (call->func && ZEND_USER_CODE(call->func->common.type)) { diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index 256c405c71c28..9b2267b531eb2 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -8,7 +8,7 @@ class stdClass } /** @refcount 1 */ -function _clone(object $object): object {} +function clone(object $object, array $withProperties = []): object {} function exit(string|int $status = 0): never {} diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 1c595ecd5777c..cf349b551ac21 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,8 +1,9 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 12327caa3fe940ccef68ed99f9278982dc0173a5 */ + * Stub hash: 9b49f527064695c812cd204d9efc63c13681d942 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_clone, 0, 1, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, withProperties, IS_ARRAY, 0, "[]") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_exit, 0, 0, IS_NEVER, 0) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 5777e1a34a2b8..22fd30463726f 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -81,14 +81,14 @@ static bool zend_valid_closure_binding( bool is_fake_closure = (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) != 0; if (newthis) { if (func->common.fn_flags & ZEND_ACC_STATIC) { - zend_error(E_WARNING, "Cannot bind an instance to a static closure"); + zend_error(E_WARNING, "Cannot bind an instance to a static closure, this will be an error in PHP 9"); return 0; } if (is_fake_closure && func->common.scope && !instanceof_function(Z_OBJCE_P(newthis), func->common.scope)) { /* Binding incompatible $this to an internal method is not supported. */ - zend_error(E_WARNING, "Cannot bind method %s::%s() to object of class %s", + zend_error(E_WARNING, "Cannot bind method %s::%s() to object of class %s, this will be an error in PHP 9", ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name), ZSTR_VAL(Z_OBJCE_P(newthis)->name)); @@ -96,26 +96,26 @@ static bool zend_valid_closure_binding( } } else if (is_fake_closure && func->common.scope && !(func->common.fn_flags & ZEND_ACC_STATIC)) { - zend_error(E_WARNING, "Cannot unbind $this of method"); + zend_error(E_WARNING, "Cannot unbind $this of method, this will be an error in PHP 9"); return 0; } else if (!is_fake_closure && !Z_ISUNDEF(closure->this_ptr) && (func->common.fn_flags & ZEND_ACC_USES_THIS)) { - zend_error(E_WARNING, "Cannot unbind $this of closure using $this"); + zend_error(E_WARNING, "Cannot unbind $this of closure using $this, this will be an error in PHP 9"); return 0; } if (scope && scope != func->common.scope && scope->type == ZEND_INTERNAL_CLASS) { /* rebinding to internal class is not allowed */ - zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s", + zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s, this will be an error in PHP 9", ZSTR_VAL(scope->name)); return 0; } if (is_fake_closure && scope != func->common.scope) { if (func->common.scope == NULL) { - zend_error(E_WARNING, "Cannot rebind scope of closure created from function"); + zend_error(E_WARNING, "Cannot rebind scope of closure created from function, this will be an error in PHP 9"); } else { - zend_error(E_WARNING, "Cannot rebind scope of closure created from method"); + zend_error(E_WARNING, "Cannot rebind scope of closure created from method, this will be an error in PHP 9"); } return 0; } @@ -418,6 +418,23 @@ ZEND_METHOD(Closure, fromCallable) } /* }}} */ +ZEND_METHOD(Closure, getCurrent) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_execute_data *prev_ex = EX(prev_execute_data); + + if (!prev_ex + || !prev_ex->func + || (prev_ex->func->common.fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_FAKE_CLOSURE)) != ZEND_ACC_CLOSURE) { + zend_throw_error(NULL, "Current function is not a closure"); + RETURN_THROWS(); + } + + zend_object *obj = ZEND_CLOSURE_OBJECT(prev_ex->func); + RETURN_OBJ_COPY(obj); +} + static ZEND_COLD zend_function *zend_closure_get_constructor(zend_object *object) /* {{{ */ { zend_throw_error(NULL, "Instantiation of class Closure is not allowed"); diff --git a/Zend/zend_closures.stub.php b/Zend/zend_closures.stub.php index daa92492b1884..46b51617eef98 100644 --- a/Zend/zend_closures.stub.php +++ b/Zend/zend_closures.stub.php @@ -21,4 +21,6 @@ public function bindTo(?object $newThis, object|string|null $newScope = "static" public function call(object $newThis, mixed ...$args): mixed {} public static function fromCallable(callable $callback): Closure {} + + public static function getCurrent(): Closure {} } diff --git a/Zend/zend_closures_arginfo.h b/Zend/zend_closures_arginfo.h index 57066078a8821..4ce02c40e55a7 100644 --- a/Zend/zend_closures_arginfo.h +++ b/Zend/zend_closures_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e3b480674671a698814db282c5ea34d438fe519d */ + * Stub hash: e0626e52adb2d38dad1140c1a28cc7774cc84500 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -24,11 +24,15 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Closure_fromCallable, 0, 1, ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Closure_getCurrent, 0, 0, Closure, 0) +ZEND_END_ARG_INFO() + ZEND_METHOD(Closure, __construct); ZEND_METHOD(Closure, bind); ZEND_METHOD(Closure, bindTo); ZEND_METHOD(Closure, call); ZEND_METHOD(Closure, fromCallable); +ZEND_METHOD(Closure, getCurrent); static const zend_function_entry class_Closure_methods[] = { ZEND_ME(Closure, __construct, arginfo_class_Closure___construct, ZEND_ACC_PRIVATE) @@ -36,6 +40,7 @@ static const zend_function_entry class_Closure_methods[] = { ZEND_ME(Closure, bindTo, arginfo_class_Closure_bindTo, ZEND_ACC_PUBLIC) ZEND_ME(Closure, call, arginfo_class_Closure_call, ZEND_ACC_PUBLIC) ZEND_ME(Closure, fromCallable, arginfo_class_Closure_fromCallable, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(Closure, getCurrent, arginfo_class_Closure_getCurrent, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END }; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f3f6d1b75aec1..ad735c41acaff 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -339,6 +339,7 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_arra CG(context).try_catch_offset = -1; CG(context).current_brk_cont = -1; CG(context).last_brk_cont = 0; + CG(context).has_assigned_to_http_response_header = false; CG(context).brk_cont_array = NULL; CG(context).labels = NULL; CG(context).in_jmp_frameless_branch = false; @@ -821,7 +822,8 @@ static void zend_do_free(znode *op1) /* {{{ */ } else { while (opline >= CG(active_op_array)->opcodes) { if ((opline->opcode == ZEND_FETCH_LIST_R || - opline->opcode == ZEND_FETCH_LIST_W) && + opline->opcode == ZEND_FETCH_LIST_W || + opline->opcode == ZEND_EXT_STMT) && opline->op1_type == IS_VAR && opline->op1.var == op1->u.op.var) { zend_emit_op(NULL, ZEND_FREE, op1, NULL); @@ -1327,7 +1329,6 @@ ZEND_API zend_class_entry *zend_bind_class_in_slot( ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname)); if (ce) { - ZEND_ASSERT(!EG(exception)); zend_observer_class_linked_notify(ce, Z_STR_P(lcname)); return ce; } @@ -1394,7 +1395,6 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop * null byte here, to avoid larger parts of the type being omitted by printing code later. */ size_t len = strlen(ZSTR_VAL(name)); if (len != ZSTR_LEN(name)) { - ZEND_ASSERT(scope && "This should only happen with resolved types"); return zend_string_init(ZSTR_VAL(name), len, 0); } return zend_string_copy(name); @@ -1922,7 +1922,7 @@ static void zend_add_to_list(void *result, void *item) /* {{{ */ } /* }}} */ -static void zend_do_extended_stmt(void) /* {{{ */ +static void zend_do_extended_stmt(znode* result) /* {{{ */ { zend_op *opline; @@ -1933,6 +1933,9 @@ static void zend_do_extended_stmt(void) /* {{{ */ opline = get_next_op(); opline->opcode = ZEND_EXT_STMT; + if (result) { + SET_NODE(opline->op1, result); + } } /* }}} */ @@ -2724,7 +2727,8 @@ static inline bool zend_is_call(zend_ast *ast) /* {{{ */ return ast->kind == ZEND_AST_CALL || ast->kind == ZEND_AST_METHOD_CALL || ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL - || ast->kind == ZEND_AST_STATIC_CALL; + || ast->kind == ZEND_AST_STATIC_CALL + || ast->kind == ZEND_AST_PIPE; } /* }}} */ @@ -2864,7 +2868,7 @@ static void zend_compile_class_ref(znode *result, zend_ast *name_ast, uint32_t f } /* }}} */ -static zend_result zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */ +static zend_result zend_try_compile_cv(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *name_ast = ast->child[0]; if (name_ast->kind == ZEND_AST_ZVAL) { @@ -2881,6 +2885,16 @@ static zend_result zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */ return FAILURE; } + if (!CG(context).has_assigned_to_http_response_header && zend_string_equals_literal(name, "http_response_header")) { + if (type == BP_VAR_R) { + zend_error(E_DEPRECATED, + "The predefined locally scoped $http_response_header variable is deprecated," + " call http_get_last_response_headers() instead"); + } else if (type == BP_VAR_W) { + CG(context).has_assigned_to_http_response_header = true; + } + } + result->op_type = IS_CV; result->u.op.var = lookup_cv(name); @@ -2917,6 +2931,14 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint opline->extended_value = ZEND_FETCH_GLOBAL; } else { + // TODO: Have a test case for this? + if (name_node.op_type == IS_CONST + && type == BP_VAR_R + && zend_string_equals_literal(Z_STR(name_node.u.constant), "http_response_header")) { + zend_error(E_DEPRECATED, + "The predefined locally scoped $http_response_header variable is deprecated," + " call http_get_last_response_headers() instead"); + } opline->extended_value = ZEND_FETCH_LOCAL; } @@ -2988,7 +3010,7 @@ static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t t result->op_type = IS_TMP_VAR; } return opline; - } else if (zend_try_compile_cv(result, ast) == FAILURE) { + } else if (zend_try_compile_cv(result, ast, type) == FAILURE) { return zend_compile_simple_var_no_cv(result, ast, type, delayed); } return NULL; @@ -3362,7 +3384,7 @@ static void zend_compile_list_assign( static void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */ { - if (ast->kind == ZEND_AST_CALL) { + if (ast->kind == ZEND_AST_CALL || ast->kind == ZEND_AST_PIPE) { zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context"); } if ( @@ -3414,7 +3436,7 @@ static void zend_compile_expr_with_potential_assign_to_self( /* $a[0] = $a should evaluate the right $a first */ znode cv_node; - if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) { + if (zend_try_compile_cv(&cv_node, expr_ast, BP_VAR_R) == FAILURE) { zend_compile_simple_var_no_cv(expr_node, expr_ast, BP_VAR_R, 0); } else { zend_emit_op_tmp(expr_node, ZEND_QM_ASSIGN, &cv_node, NULL); @@ -3504,7 +3526,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ /* list($a, $b) = $a should evaluate the right $a first */ znode cv_node; - if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) { + if (zend_try_compile_cv(&cv_node, expr_ast, BP_VAR_R) == FAILURE) { zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0); } else { zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL); @@ -3819,7 +3841,7 @@ static uint32_t zend_compile_args( opcode = ZEND_SEND_VAR_EX; CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS; break; - } else if (zend_try_compile_cv(&arg_node, arg) == SUCCESS) { + } else if (zend_try_compile_cv(&arg_node, arg, BP_VAR_R) == SUCCESS) { opcode = ZEND_SEND_VAR_EX; break; } @@ -4144,17 +4166,19 @@ static zend_result zend_compile_func_defined(znode *result, zend_ast_list *args) } /* }}} */ -static zend_result zend_compile_func_chr(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_chr(znode *result, const zend_ast_list *args) /* {{{ */ { - - if (args->children == 1 && - args->child[0]->kind == ZEND_AST_ZVAL && - Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_LONG) { - - zend_long c = Z_LVAL_P(zend_ast_get_zval(args->child[0])) & 0xff; - + zval *zint; + if ( + args->children == 1 + && args->child[0]->kind == ZEND_AST_ZVAL + && (zint = zend_ast_get_zval(args->child[0])) + && Z_TYPE_P(zint) == IS_LONG + && Z_LVAL_P(zint) >= 0 + && Z_LVAL_P(zint) <= 255 + ) { result->op_type = IS_CONST; - ZVAL_CHAR(&result->u.constant, c); + ZVAL_CHAR(&result->u.constant, Z_LVAL_P(zint)); return SUCCESS; } else { return FAILURE; @@ -4162,14 +4186,18 @@ static zend_result zend_compile_func_chr(znode *result, zend_ast_list *args) /* } /* }}} */ -static zend_result zend_compile_func_ord(znode *result, zend_ast_list *args) /* {{{ */ +static zend_result zend_compile_func_ord(znode *result, const zend_ast_list *args) /* {{{ */ { - if (args->children == 1 && - args->child[0]->kind == ZEND_AST_ZVAL && - Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_STRING) { - + zval *str; + if ( + args->children == 1 + && args->child[0]->kind == ZEND_AST_ZVAL + && (str = zend_ast_get_zval(args->child[0])) + && Z_TYPE_P(str) == IS_STRING + && Z_STRLEN_P(str) == 1 + ) { result->op_type = IS_CONST; - ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(zend_ast_get_zval(args->child[0]))[0]); + ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(str)[0]); return SUCCESS; } else { return FAILURE; @@ -4367,7 +4395,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string ZSTR_INIT_LITERAL("description", 0)); arg = zend_ast_create(ZEND_AST_NAMED_ARG, name, arg); } - zend_ast_list_add((zend_ast *) args, arg); + args = (zend_ast_list *)zend_ast_list_add((zend_ast *) args, arg); } zend_compile_call_common(result, (zend_ast*)args, fbc, lineno); @@ -5422,7 +5450,7 @@ static void zend_compile_global_var(zend_ast *ast) /* {{{ */ // TODO(GLOBALS) Forbid "global $GLOBALS"? if (is_this_fetch(var_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable"); - } else if (zend_try_compile_cv(&result, var_ast) == SUCCESS) { + } else if (zend_try_compile_cv(&result, var_ast, BP_VAR_R) == SUCCESS) { zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node); opline->extended_value = zend_alloc_cache_slot(); } else { @@ -5548,7 +5576,7 @@ static void zend_compile_unset(zend_ast *ast) /* {{{ */ case ZEND_AST_VAR: if (is_this_fetch(var_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot unset $this"); - } else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) { + } else if (zend_try_compile_cv(&var_node, var_ast, BP_VAR_UNSET) == SUCCESS) { opline = zend_emit_op(NULL, ZEND_UNSET_CV, &var_node, NULL); } else { opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, 0); @@ -5701,8 +5729,20 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0); } + uint32_t opnum_before_finally = get_next_op_number(); + zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL); + /* Content of reference might have changed in finally, repeat type check. */ + if (by_ref + /* Check if any opcodes were emitted since the last return type check. */ + && opnum_before_finally != get_next_op_number() + && !is_generator + && (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) { + zend_emit_return_type_check( + expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0); + } + opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, &expr_node, NULL); @@ -6040,7 +6080,7 @@ static void zend_compile_for(zend_ast *ast) /* {{{ */ zend_update_jump_target_to_next(opnum_jmp); zend_compile_for_expr_list(&result, cond_ast); - zend_do_extended_stmt(); + zend_do_extended_stmt(NULL); zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start); @@ -6099,7 +6139,7 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */ if (is_this_fetch(value_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this"); } else if (value_ast->kind == ZEND_AST_VAR && - zend_try_compile_cv(&value_node, value_ast) == SUCCESS) { + zend_try_compile_cv(&value_node, value_ast, BP_VAR_R) == SUCCESS) { SET_NODE(opline->op2, &value_node); } else { opline->op2_type = IS_VAR; @@ -6161,7 +6201,7 @@ static void zend_compile_if(zend_ast *ast) /* {{{ */ if (i > 0) { CG(zend_lineno) = cond_ast->lineno; - zend_do_extended_stmt(); + zend_do_extended_stmt(NULL); } zend_compile_expr(&cond_node, cond_ast); @@ -6303,6 +6343,11 @@ static void zend_compile_switch(zend_ast *ast) /* {{{ */ continue; } + if (case_ast->attr == ZEND_ALT_CASE_SYNTAX) { + CG(zend_lineno) = case_ast->lineno; + zend_error(E_DEPRECATED, "Case statements followed by a semicolon (;) are deprecated, use a colon (:) instead"); + } + zend_compile_expr(&cond_node, cond_ast); if (expr_node.op_type == IS_CONST @@ -6426,11 +6471,29 @@ static bool can_match_use_jumptable(zend_ast_list *arms) { return 1; } +static bool zend_is_pipe_optimizable_callable_name(zend_ast *ast) +{ + if (ast->kind == ZEND_AST_ZVAL && Z_TYPE_P(zend_ast_get_zval(ast)) == IS_STRING) { + /* Assert compilation adds a message operand, but this is incompatible with the + * pipe optimization that uses a temporary znode for the reference elimination. + * Therefore, disable the optimization for assert. + * Note that "assert" as a name is always treated as fully qualified. */ + zend_string *str = zend_ast_get_str(ast); + return !zend_string_equals_literal_ci(str, "assert"); + } + + return true; +} + static void zend_compile_pipe(znode *result, zend_ast *ast) { zend_ast *operand_ast = ast->child[0]; zend_ast *callable_ast = ast->child[1]; + if (callable_ast->kind == ZEND_AST_ARROW_FUNC && !(callable_ast->attr & ZEND_PARENTHESIZED_ARROW_FUNC)) { + zend_error_noreturn(E_COMPILE_ERROR, "Arrow functions on the right hand side of |> must be parenthesized"); + } + /* Compile the left hand side down to a value first. */ znode operand_result; zend_compile_expr(&operand_result, operand_ast); @@ -6453,7 +6516,8 @@ static void zend_compile_pipe(znode *result, zend_ast *ast) /* Turn $foo |> bar(...) into bar($foo). */ if (callable_ast->kind == ZEND_AST_CALL - && callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) { + && callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT + && zend_is_pipe_optimizable_callable_name(callable_ast->child[0])) { fcall_ast = zend_ast_create(ZEND_AST_CALL, callable_ast->child[0], arg_list_ast); /* Turn $foo |> bar::baz(...) into bar::baz($foo). */ @@ -6474,6 +6538,8 @@ static void zend_compile_pipe(znode *result, zend_ast *ast) callable_ast, arg_list_ast); } + zend_do_extended_stmt(&operand_result); + zend_compile_expr(result, fcall_ast); } @@ -7052,16 +7118,20 @@ static zend_type zend_compile_single_typename(zend_ast *ast) ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_SELF || fetch_type == ZEND_FETCH_CLASS_PARENT); zend_ensure_valid_class_fetch_type(fetch_type); + + bool substitute_self_parent = zend_is_scope_known() + && !(CG(active_class_entry)->ce_flags & ZEND_ACC_ANON_CLASS); + if (fetch_type == ZEND_FETCH_CLASS_SELF) { /* Scope might be unknown for unbound closures and traits */ - if (zend_is_scope_known()) { + if (substitute_self_parent) { class_name = CG(active_class_entry)->name; ZEND_ASSERT(class_name && "must know class name when resolving self type at compile time"); } } else { ZEND_ASSERT(fetch_type == ZEND_FETCH_CLASS_PARENT); /* Scope might be unknown for unbound closures and traits */ - if (zend_is_scope_known()) { + if (substitute_self_parent) { class_name = CG(active_class_entry)->parent_name; ZEND_ASSERT(class_name && "must know class name when resolving parent type at compile time"); } @@ -7518,19 +7588,41 @@ static void zend_compile_attributes( } if (*attributes != NULL) { + /* Allow delaying target validation for forward compatibility. */ + zend_attribute *delayed_target_validation = NULL; + if (target == ZEND_ATTRIBUTE_TARGET_PARAMETER) { + ZEND_ASSERT(offset >= 1); + /* zend_get_parameter_attribute_str will add 1 too */ + delayed_target_validation = zend_get_parameter_attribute_str( + *attributes, + "delayedtargetvalidation", + strlen("delayedtargetvalidation"), + offset - 1 + ); + } else { + delayed_target_validation = zend_get_attribute_str( + *attributes, + "delayedtargetvalidation", + strlen("delayedtargetvalidation") + ); + } /* Validate attributes in a secondary loop (needed to detect repeated attributes). */ ZEND_HASH_PACKED_FOREACH_PTR(*attributes, attr) { if (attr->offset != offset || NULL == (config = zend_internal_attribute_get(attr->lcname))) { continue; } + bool run_validator = true; if (!(target & (config->flags & ZEND_ATTRIBUTE_TARGET_ALL))) { - zend_string *location = zend_get_attribute_target_names(target); - zend_string *allowed = zend_get_attribute_target_names(config->flags); + if (delayed_target_validation == NULL) { + zend_string *location = zend_get_attribute_target_names(target); + zend_string *allowed = zend_get_attribute_target_names(config->flags); - zend_error_noreturn(E_ERROR, "Attribute \"%s\" cannot target %s (allowed targets: %s)", - ZSTR_VAL(attr->name), ZSTR_VAL(location), ZSTR_VAL(allowed) - ); + zend_error_noreturn(E_ERROR, "Attribute \"%s\" cannot target %s (allowed targets: %s)", + ZSTR_VAL(attr->name), ZSTR_VAL(location), ZSTR_VAL(allowed) + ); + } + run_validator = false; } if (!(config->flags & ZEND_ATTRIBUTE_IS_REPEATABLE)) { @@ -7539,8 +7631,17 @@ static void zend_compile_attributes( } } - if (config->validator != NULL) { - config->validator(attr, target, CG(active_class_entry)); + /* Validators are not run if the target is already invalid */ + if (run_validator && config->validator != NULL) { + zend_string *error = config->validator(attr, target, CG(active_class_entry)); + if (error != NULL) { + if (delayed_target_validation == NULL) { + zend_error_noreturn(E_COMPILE_ERROR, "%s", ZSTR_VAL(error)); + zend_string_efree(error); + } else { + attr->validation_error = error; + } + } } } ZEND_HASH_FOREACH_END(); } @@ -7683,6 +7784,8 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL); bool is_promoted = property_flags || hooks_ast; + CG(zend_lineno) = param_ast->lineno; + znode var_node, default_node; uint8_t opcode; zend_op *opline; @@ -7701,6 +7804,8 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 ZSTR_VAL(name)); } else if (zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS))) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as parameter"); + } else if (zend_string_equals_literal(name, "http_response_header")) { + CG(context).has_assigned_to_http_response_header = true; } if (op_array->fn_flags & ZEND_ACC_VARIADIC) { @@ -7880,6 +7985,11 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 if (attributes_ast) { zend_compile_attributes( &prop->attributes, attributes_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, ZEND_ATTRIBUTE_TARGET_PARAMETER); + + zend_attribute *override_attribute = zend_get_attribute_str(prop->attributes, "override", sizeof("override")-1); + if (override_attribute) { + prop->flags |= ZEND_ACC_OVERRIDE; + } } } } @@ -7904,6 +8014,8 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 continue; } + CG(zend_lineno) = param_ast->lineno; + /* Emit $this->prop = $prop for promoted properties. */ zend_string *name = zend_ast_get_str(param_ast->child[1]); znode name_node, value_node; @@ -8377,6 +8489,10 @@ static zend_op_array *zend_compile_func_decl_ex( CG(active_op_array) = op_array; + zend_oparray_context_begin(&orig_oparray_context, op_array); + CG(context).active_property_info_name = property_info_name; + CG(context).active_property_hook_kind = hook_kind; + if (decl->child[4]) { int target = ZEND_ATTRIBUTE_TARGET_FUNCTION; @@ -8406,15 +8522,7 @@ static zend_op_array *zend_compile_func_decl_ex( op_array->fn_flags |= ZEND_ACC_DEPRECATED; } - zend_attribute *nodiscard_attribute = zend_get_attribute_str( - op_array->attributes, - "nodiscard", - sizeof("nodiscard")-1 - ); - - if (nodiscard_attribute) { - op_array->fn_flags |= ZEND_ACC_NODISCARD; - } + // ZEND_ACC_NODISCARD is added via an attribute validator } /* Do not leak the class scope into free standing functions, even if they are dynamically @@ -8428,10 +8536,6 @@ static zend_op_array *zend_compile_func_decl_ex( op_array->fn_flags |= ZEND_ACC_TOP_LEVEL; } - zend_oparray_context_begin(&orig_oparray_context, op_array); - CG(context).active_property_info_name = property_info_name; - CG(context).active_property_hook_kind = hook_kind; - { /* Push a separator to the loop variable stack */ zend_loop_var dummy_var; @@ -8466,9 +8570,12 @@ static zend_op_array *zend_compile_func_decl_ex( } if (op_array->fn_flags & ZEND_ACC_NODISCARD) { - if (is_hook) { - zend_error_noreturn(E_COMPILE_ERROR, "#[\\NoDiscard] is not supported for property hooks"); - } + /* ZEND_ACC_NODISCARD gets added by the attribute validator, but only + * if the method is not a hook; if it is a hook, then the validator + * will have returned an error message, even if the error message was + * delayed with #[\DelayedTargetValidation] that ZEND_ACC_NODISCARD + * flag should not have been added. */ + ZEND_ASSERT(!is_hook); if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { zend_arg_info *return_info = CG(active_op_array)->arg_info - 1; @@ -8503,7 +8610,7 @@ static zend_op_array *zend_compile_func_decl_ex( /* put the implicit return on the really last line */ CG(zend_lineno) = decl->end_lineno; - zend_do_extended_stmt(); + zend_do_extended_stmt(NULL); zend_emit_final_return(0); pass_two(CG(active_op_array)); @@ -8857,6 +8964,11 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f if (attr_ast) { zend_compile_attributes(&info->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_PROPERTY, 0); + + zend_attribute *override_attribute = zend_get_attribute_str(info->attributes, "override", sizeof("override")-1); + if (override_attribute) { + info->flags |= ZEND_ACC_OVERRIDE; + } } CG(context).active_property_info_name = old_active_property_info_name; @@ -9243,6 +9355,15 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) ce->ce_flags |= ZEND_ACC_TOP_LEVEL; } + if (ce->__serialize == NULL && zend_hash_exists(&ce->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP))) { + zend_error(E_DEPRECATED, "The __sleep() serialization magic method has been deprecated." + " Implement __serialize() instead (or in addition, if support for old PHP versions is necessary)"); + } + if (ce->__unserialize == NULL && zend_hash_exists(&ce->function_table, ZSTR_KNOWN(ZEND_STR_WAKEUP))) { + zend_error(E_DEPRECATED, "The __wakeup() serialization magic method has been deprecated." + " Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary)"); + } + /* We currently don't early-bind classes that implement interfaces or use traits */ if (!ce->num_interfaces && !ce->num_traits && !ce->num_hooked_prop_variance_checks #ifdef ZEND_OPCACHE_SHM_REATTACHMENT @@ -9702,7 +9823,11 @@ static void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */ name = zend_mangle_property_name(const_name, sizeof(const_name) - 1, ZSTR_VAL(filename), ZSTR_LEN(filename), 0); - zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), offset, 0, 0); + /* Avoid repeated declaration of the __COMPILER_HALT_OFFSET__ constant in + * case this file was already included. */ + if (!zend_hash_find(EG(zend_constants), name)) { + zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), offset, 0, 0); + } zend_string_release_ex(name, 0); } /* }}} */ @@ -10751,7 +10876,7 @@ static void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ if (is_this_fetch(var_ast)) { opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_THIS, NULL, NULL); CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS; - } else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) { + } else if (zend_try_compile_cv(&var_node, var_ast, BP_VAR_IS) == SUCCESS) { opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_CV, &var_node, NULL); } else { opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, 0); @@ -10807,6 +10932,8 @@ static void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */ zval fn_name; zend_ast *name_ast, *args_ast, *call_ast; + zend_error(E_DEPRECATED, "The backtick (`) operator is deprecated, use shell_exec() instead"); + ZVAL_STRING(&fn_name, "shell_exec"); name_ast = zend_ast_create_zval(&fn_name); args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast); @@ -11573,7 +11700,7 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */ CG(zend_lineno) = ast->lineno; if ((CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT) && !zend_is_unticked_stmt(ast)) { - zend_do_extended_stmt(); + zend_do_extended_stmt(NULL); } switch (ast->kind) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 62d0fbcded2ee..c07fa9bfa7d7e 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -24,6 +24,7 @@ #include "zend_types.h" #include "zend_map_ptr.h" #include "zend_alloc.h" +#include "zend_vm_opcodes.h" #include #include @@ -96,7 +97,7 @@ typedef struct _zend_ast_znode { znode node; } zend_ast_znode; -ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node); +ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(const znode *node); static zend_always_inline znode *zend_ast_get_znode(zend_ast *ast) { return &((zend_ast_znode *) ast)->node; @@ -135,7 +136,7 @@ void zend_const_expr_to_zval(zval *result, zend_ast **ast_ptr, bool allow_dynami typedef int (*user_opcode_handler_t) (zend_execute_data *execute_data); struct _zend_op { - const void *handler; + zend_vm_opcode_handler_t handler; znode_op op1; znode_op op2; znode_op result; @@ -207,6 +208,7 @@ typedef struct _zend_oparray_context { zend_string *active_property_info_name; zend_property_hook_kind active_property_hook_kind; bool in_jmp_frameless_branch; + bool has_assigned_to_http_response_header; } zend_oparray_context; /* Class, property and method flags class|meth.|prop.|const*/ @@ -251,9 +253,15 @@ typedef struct _zend_oparray_context { /* Flag to differentiate cases from constants. | | | */ /* Must not conflict with ZEND_ACC_ visibility flags | | | */ /* or IS_CONSTANT_VISITED_MARK | | | */ -#define ZEND_CLASS_CONST_IS_CASE (1 << 6) /* | | | X */ +#define ZEND_CLASS_CONST_IS_CASE (1 << 6) /* | | | X */ +/* | | | */ +/* deprecation flag | | | */ +#define ZEND_ACC_DEPRECATED (1 << 11) /* X | X | | X */ +/* | | | */ +/* has #[\Override] attribute | | | */ +#define ZEND_ACC_OVERRIDE (1 << 28) /* | X | X | */ /* | | | */ -/* Property Flags (unused: 13...) | | | */ +/* Property Flags (unused: 13-27,29...) | | | */ /* =========== | | | */ /* | | | */ /* Promoted property / parameter | | | */ @@ -267,7 +275,7 @@ typedef struct _zend_oparray_context { #define ZEND_ACC_PROTECTED_SET (1 << 11) /* | | X | */ #define ZEND_ACC_PRIVATE_SET (1 << 12) /* | | X | */ /* | | | */ -/* Class Flags (unused: 30,31) | | | */ +/* Class Flags (unused: 31) | | | */ /* =========== | | | */ /* | | | */ /* Special class types | | | */ @@ -285,7 +293,7 @@ typedef struct _zend_oparray_context { /* | | | */ /* Class has magic methods __get/__set/__unset/ | | | */ /* __isset that use guards | | | */ -#define ZEND_ACC_USE_GUARDS (1 << 11) /* X | | | */ +#define ZEND_ACC_USE_GUARDS (1 << 30) /* X | | | */ /* | | | */ /* Class constants updated | | | */ #define ZEND_ACC_CONSTANTS_UPDATED (1 << 12) /* X | | | */ @@ -336,9 +344,6 @@ typedef struct _zend_oparray_context { /* Function Flags (unused: 30) | | | */ /* ============== | | | */ /* | | | */ -/* deprecation flag | | | */ -#define ZEND_ACC_DEPRECATED (1 << 11) /* | X | | X */ -/* | | | */ /* Function returning by reference | | | */ #define ZEND_ACC_RETURN_REFERENCE (1 << 12) /* | X | | */ /* | | | */ @@ -392,9 +397,6 @@ typedef struct _zend_oparray_context { /* supports opcache compile-time evaluation (funcs) | | | */ #define ZEND_ACC_COMPILE_TIME_EVAL (1 << 27) /* | X | | */ /* | | | */ -/* has #[\Override] attribute | | | */ -#define ZEND_ACC_OVERRIDE (1 << 28) /* | X | | */ -/* | | | */ /* Has IS_PTR operands that needs special cleaning; same | | | */ /* value as ZEND_ACC_OVERRIDE but override is for class | | | */ /* methods and this is for the top level op array | | | */ @@ -886,7 +888,6 @@ ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_ar #ifdef ZTS const char *zend_get_zendtext(void); -int zend_get_zendleng(void); #endif typedef zend_result (ZEND_FASTCALL *unary_op_type)(zval *, zval *); @@ -1127,6 +1128,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type); ((ZEND_TYPE_FULL_MASK((arg_info)->type) & _ZEND_IS_TENTATIVE_BIT) != 0) #define ZEND_DIM_IS (1 << 0) /* isset fetch needed for null coalesce. Set in zend_compile.c for ZEND_AST_DIM nested within ZEND_AST_COALESCE. */ +#define ZEND_ALT_CASE_SYNTAX (1 << 1) /* deprecated switch case terminated by semicolon */ /* Attributes for ${} encaps var in strings (ZEND_AST_DIM or ZEND_AST_VAR node) */ /* ZEND_AST_VAR nodes can have any of the ZEND_ENCAPS_VAR_* flags */ @@ -1206,6 +1208,9 @@ static zend_always_inline bool zend_check_arg_send_type(const zend_function *zf, /* Used to distinguish (parent::$prop)::get() from parent hook call. */ #define ZEND_PARENTHESIZED_STATIC_PROP 1 +/* Used to disallow pipes with arrow functions that lead to confusing parse trees. */ +#define ZEND_PARENTHESIZED_ARROW_FUNC 1 + /* For "use" AST nodes and the seen symbol table */ #define ZEND_SYMBOL_CLASS (1<<0) #define ZEND_SYMBOL_FUNCTION (1<<1) diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index ffad8315ae40d..a18c393be7f98 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -136,62 +136,62 @@ void zend_register_standard_constants(void) null_const = zend_hash_str_find_ptr(EG(zend_constants), "NULL", sizeof("NULL")-1); } -ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number) +ZEND_API zend_constant *zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number) { zend_constant c; ZVAL_NULL(&c.value); ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number); c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT); - zend_register_constant(&c); + return zend_register_constant(&c); } -ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, bool bval, int flags, int module_number) +ZEND_API zend_constant *zend_register_bool_constant(const char *name, size_t name_len, bool bval, int flags, int module_number) { zend_constant c; ZVAL_BOOL(&c.value, bval); ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number); c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT); - zend_register_constant(&c); + return zend_register_constant(&c); } -ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number) +ZEND_API zend_constant *zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number) { zend_constant c; ZVAL_LONG(&c.value, lval); ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number); c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT); - zend_register_constant(&c); + return zend_register_constant(&c); } -ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number) +ZEND_API zend_constant *zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number) { zend_constant c; ZVAL_DOUBLE(&c.value, dval); ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number); c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT); - zend_register_constant(&c); + return zend_register_constant(&c); } -ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number) +ZEND_API zend_constant *zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number) { zend_constant c; ZVAL_STR(&c.value, zend_string_init_interned(strval, strlen, flags & CONST_PERSISTENT)); ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number); c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT); - zend_register_constant(&c); + return zend_register_constant(&c); } -ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number) +ZEND_API zend_constant *zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number) { - zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number); + return zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number); } static zend_constant *zend_get_halt_offset_constant(const char *name, size_t name_len) @@ -487,6 +487,9 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, CONST_PROTECT_RECURSION(c); zend_deprecated_constant(c, c->name); CONST_UNPROTECT_RECURSION(c); + if (UNEXPECTED(EG(exception))) { + return NULL; + } } } return &c->value; @@ -505,11 +508,11 @@ static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_consta return ret; } -ZEND_API zend_result zend_register_constant(zend_constant *c) +ZEND_API zend_constant *zend_register_constant(zend_constant *c) { zend_string *lowercase_name = NULL; zend_string *name; - zend_result ret = SUCCESS; + zend_constant *ret = NULL; bool persistent = (ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) != 0; #if 0 @@ -539,9 +542,9 @@ ZEND_API zend_result zend_register_constant(zend_constant *c) /* Check if the user is trying to define any special constant */ if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__") || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name))) - || zend_hash_add_constant(EG(zend_constants), name, c) == NULL + || (ret = zend_hash_add_constant(EG(zend_constants), name, c)) == NULL ) { - zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name)); + zend_error(E_WARNING, "Constant %s already defined, this will be an error in PHP 9", ZSTR_VAL(name)); zend_string_release(c->name); if (c->filename) { zend_string_release(c->filename); @@ -550,7 +553,6 @@ ZEND_API zend_result zend_register_constant(zend_constant *c) if (!persistent) { zval_ptr_dtor_nogc(&c->value); } - ret = FAILURE; } if (lowercase_name) { zend_string_release(lowercase_name); diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index 3912215d80775..6bdb19c4d5afc 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -91,13 +91,13 @@ ZEND_API zend_constant *zend_get_constant_ptr(zend_string *name); ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len); ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, uint32_t flags); ZEND_API zval *zend_get_class_constant_ex(zend_string *class_name, zend_string *constant_name, zend_class_entry *scope, uint32_t flags); -ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, bool bval, int flags, int module_number); -ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number); -ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number); -ZEND_API void zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number); -ZEND_API void zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number); -ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number); -ZEND_API zend_result zend_register_constant(zend_constant *c); +ZEND_API zend_constant *zend_register_bool_constant(const char *name, size_t name_len, bool bval, int flags, int module_number); +ZEND_API zend_constant *zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number); +ZEND_API zend_constant *zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number); +ZEND_API zend_constant *zend_register_double_constant(const char *name, size_t name_len, double dval, int flags, int module_number); +ZEND_API zend_constant *zend_register_string_constant(const char *name, size_t name_len, const char *strval, int flags, int module_number); +ZEND_API zend_constant *zend_register_stringl_constant(const char *name, size_t name_len, const char *strval, size_t strlen, int flags, int module_number); +ZEND_API zend_constant *zend_register_constant(zend_constant *c); void zend_constant_add_attributes(zend_constant *c, HashTable *attributes); #ifdef ZTS void zend_copy_constants(HashTable *target, HashTable *source); diff --git a/Zend/zend_constants.stub.php b/Zend/zend_constants.stub.php index 763b207641f69..e511dc8808668 100644 --- a/Zend/zend_constants.stub.php +++ b/Zend/zend_constants.stub.php @@ -121,20 +121,23 @@ */ const ZEND_DEBUG_BUILD = UNKNOWN; +/** + * @var string + * @cvalue zend_vm_kind_name[ZEND_VM_KIND] + */ +const ZEND_VM_KIND = UNKNOWN; + /* Special constants true/false/null. */ /** - * @var bool * @undocumentable */ const TRUE = true; /** - * @var bool * @undocumentable */ const FALSE = false; /** - * @var null * @undocumentable */ const NULL = null; diff --git a/Zend/zend_constants_arginfo.h b/Zend/zend_constants_arginfo.h index d381bcf64ee18..316b7e37615fd 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: 5e224893a5fb72b3f93249235c2a1634233ce505 */ + * Stub hash: 569ccba4e0a93a9ce49c81c76955413188df390e */ static void register_zend_constants_symbols(int module_number) { @@ -14,7 +14,7 @@ static void register_zend_constants_symbols(int module_number) REGISTER_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_E_STRICT = REGISTER_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED, CONST_PERSISTENT); @@ -23,21 +23,16 @@ static void register_zend_constants_symbols(int module_number) REGISTER_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT); REGISTER_BOOL_CONSTANT("ZEND_THREAD_SAFE", ZTS_V, CONST_PERSISTENT); REGISTER_BOOL_CONSTANT("ZEND_DEBUG_BUILD", ZEND_DEBUG, CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("ZEND_VM_KIND", zend_vm_kind_name[ZEND_VM_KIND], CONST_PERSISTENT); REGISTER_BOOL_CONSTANT("TRUE", true, CONST_PERSISTENT); REGISTER_BOOL_CONSTANT("FALSE", false, CONST_PERSISTENT); REGISTER_NULL_CONSTANT("NULL", CONST_PERSISTENT); - zend_constant *const_E_STRICT = zend_hash_str_find_ptr(EG(zend_constants), "E_STRICT", sizeof("E_STRICT") - 1); zend_attribute *attribute_Deprecated_const_E_STRICT_0 = zend_add_global_constant_attribute(const_E_STRICT, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_const_E_STRICT_0_arg0; - zend_string *attribute_Deprecated_const_E_STRICT_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_const_E_STRICT_0_arg0, attribute_Deprecated_const_E_STRICT_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_E_STRICT_0->args[0].value, &attribute_Deprecated_const_E_STRICT_0_arg0); + ZVAL_STR(&attribute_Deprecated_const_E_STRICT_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_const_E_STRICT_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_const_E_STRICT_0_arg1; zend_string *attribute_Deprecated_const_E_STRICT_0_arg1_str = zend_string_init("the error level was removed", strlen("the error level was removed"), 1); - ZVAL_STR(&attribute_Deprecated_const_E_STRICT_0_arg1, attribute_Deprecated_const_E_STRICT_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_E_STRICT_0->args[1].value, &attribute_Deprecated_const_E_STRICT_0_arg1); + ZVAL_STR(&attribute_Deprecated_const_E_STRICT_0->args[1].value, attribute_Deprecated_const_E_STRICT_0_arg1_str); attribute_Deprecated_const_E_STRICT_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 212fe3cb7ab66..0b0945aac0f44 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -67,7 +67,7 @@ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entr { /* zend_ce_exception and zend_ce_error may not be initialized yet when this is called (e.g when * implementing Throwable for Exception itself). Perform a manual inheritance check. */ - zend_class_entry *root = class_type; + const zend_class_entry *root = class_type; while (root->parent) { root = root->parent; } @@ -89,13 +89,13 @@ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entr } /* }}} */ -static inline zend_class_entry *i_get_exception_base(zend_object *object) /* {{{ */ +static inline zend_class_entry *i_get_exception_base(const zend_object *object) /* {{{ */ { return instanceof_function(object->ce, zend_ce_exception) ? zend_ce_exception : zend_ce_error; } /* }}} */ -ZEND_API zend_class_entry *zend_get_exception_base(zend_object *object) /* {{{ */ +ZEND_API zend_class_entry *zend_get_exception_base(const zend_object *object) /* {{{ */ { return i_get_exception_base(object); } @@ -192,7 +192,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /* #endif /* HAVE_DTRACE */ if (exception != NULL) { - zend_object *previous = EG(exception); + const zend_object *previous = EG(exception); if (previous && zend_is_unwind_exit(previous)) { /* Don't replace unwinding exception with different exception. */ OBJ_RELEASE(exception); @@ -274,7 +274,7 @@ static void zend_update_property_num_checked(zend_class_entry *scope, zend_objec return; } #if ZEND_DEBUG - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = i_get_exception_base(object); const zend_property_info *prop_info = zend_get_property_info(object->ce, member, true); ZEND_ASSERT(OBJ_PROP_TO_NUM(prop_info->offset) == prop_num); @@ -695,16 +695,33 @@ ZEND_METHOD(Exception, __toString) zval trace, *exception; zend_class_entry *base_ce; zend_string *str; - zend_fcall_info fci; zval rv, tmp; - zend_string *fname; ZEND_PARSE_PARAMETERS_NONE(); str = ZSTR_EMPTY_ALLOC(); exception = ZEND_THIS; - fname = ZSTR_INIT_LITERAL("gettraceasstring", 0); + base_ce = i_get_exception_base(Z_OBJ_P(exception)); + + /* As getTraceAsString method is final we can grab it once */ + zend_function *getTraceAsString = zend_hash_str_find_ptr(&base_ce->function_table, ZEND_STRL("gettraceasstring")); + ZEND_ASSERT(getTraceAsString && "Method getTraceAsString must exist"); + + + zend_fcall_info fci; + fci.size = sizeof(fci); + ZVAL_UNDEF(&fci.function_name); + fci.retval = &trace; + fci.param_count = 0; + fci.params = NULL; + fci.object = NULL; + fci.named_params = NULL; + + zend_fcall_info_cache fcc; + fcc.function_handler = getTraceAsString; + fcc.called_scope = base_ce; + fcc.closure = NULL; while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), zend_ce_throwable)) { zend_string *prev_str = str; @@ -712,15 +729,9 @@ ZEND_METHOD(Exception, __toString) zend_string *file = zval_get_string(GET_PROPERTY(exception, ZEND_STR_FILE)); zend_long line = zval_get_long(GET_PROPERTY(exception, ZEND_STR_LINE)); - fci.size = sizeof(fci); - ZVAL_STR(&fci.function_name, fname); - fci.object = Z_OBJ_P(exception); - fci.retval = &trace; - fci.param_count = 0; - fci.params = NULL; - fci.named_params = NULL; - - zend_call_function(&fci, NULL); + fcc.object = Z_OBJ_P(exception); + fcc.calling_scope = Z_OBJCE_P(exception); + zend_call_function(&fci, &fcc); if (Z_TYPE(trace) != IS_STRING) { zval_ptr_dtor(&trace); @@ -765,11 +776,11 @@ ZEND_METHOD(Exception, __toString) break; } } - zend_string_release_ex(fname, 0); exception = ZEND_THIS; /* Reset apply counts */ - while (Z_TYPE_P(exception) == IS_OBJECT && (base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), base_ce)) { + zend_class_entry *previous_base_ce; + while (Z_TYPE_P(exception) == IS_OBJECT && (previous_base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), previous_base_ce)) { if (Z_IS_RECURSIVE_P(exception)) { Z_UNPROTECT_RECURSION_P(exception); } else { @@ -779,13 +790,10 @@ ZEND_METHOD(Exception, __toString) ZVAL_DEREF(exception); } - exception = ZEND_THIS; - base_ce = i_get_exception_base(Z_OBJ_P(exception)); - /* We store the result in the private property string so we can access * the result in uncaught exception handlers without memleaks. */ ZVAL_STR(&tmp, str); - zend_update_property_ex(base_ce, Z_OBJ_P(exception), ZSTR_KNOWN(ZEND_STR_STRING), &tmp); + zend_update_property_ex(base_ce, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_STRING), &tmp); RETURN_STR(str); } @@ -846,20 +854,6 @@ void zend_register_default_exception(void) /* {{{ */ } /* }}} */ -/* {{{ Deprecated - Use zend_ce_exception directly instead */ -ZEND_API zend_class_entry *zend_exception_get_default(void) -{ - return zend_ce_exception; -} -/* }}} */ - -/* {{{ Deprecated - Use zend_ce_error_exception directly instead */ -ZEND_API zend_class_entry *zend_get_error_exception(void) -{ - return zend_ce_error_exception; -} -/* }}} */ - static zend_object *zend_throw_exception_zstr(zend_class_entry *exception_ce, zend_string *message, zend_long code) /* {{{ */ { zval ex, tmp; diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 35f6699559421..24d9f4efd80a3 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -48,13 +48,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception); void zend_register_default_exception(void); -ZEND_API zend_class_entry *zend_get_exception_base(zend_object *object); - -/* Deprecated - Use zend_ce_exception directly instead */ -ZEND_API zend_class_entry *zend_exception_get_default(void); - -/* Deprecated - Use zend_ce_error_exception directly instead */ -ZEND_API zend_class_entry *zend_get_error_exception(void); +ZEND_API zend_class_entry *zend_get_exception_base(const zend_object *object); ZEND_API void zend_register_default_classes(void); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5d8d9f4caeb86..385fe9af0bbfe 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -932,7 +932,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_object_released_while_assigning_to_pr ZEND_API ZEND_COLD void ZEND_FASTCALL zend_asymmetric_visibility_property_modification_error( const zend_property_info *prop_info, const char *operation ) { - zend_class_entry *scope; + const zend_class_entry *scope; if (EG(fake_scope)) { scope = EG(fake_scope); } else { @@ -2006,6 +2006,27 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_consta zend_string_release(message_suffix); } +ZEND_API ZEND_COLD void zend_use_of_deprecated_trait( + zend_class_entry *trait, + const zend_string *used_by +) { + zend_string *message_suffix = ZSTR_EMPTY_ALLOC(); + + if (get_deprecation_suffix_from_attribute(trait->attributes, trait, &message_suffix) == FAILURE) { + return; + } + + int code = trait->type == ZEND_INTERNAL_CLASS ? E_DEPRECATED : E_USER_DEPRECATED; + + zend_error_unchecked(code, "Trait %s used by %s is deprecated%S", + ZSTR_VAL(trait->name), + ZSTR_VAL(used_by), + message_suffix + ); + + zend_string_release(message_suffix); +} + ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void) { zend_error(E_DEPRECATED, "Automatic conversion of false to array is deprecated"); @@ -2629,6 +2650,21 @@ static zend_never_inline uint8_t slow_index_convert(HashTable *ht, const zval *d ZEND_FALLTHROUGH; } case IS_NULL: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return IS_NULL; + } + + if (EG(exception)) { + return IS_NULL; + } + value->str = ZSTR_EMPTY_ALLOC(); return IS_STRING; case IS_DOUBLE: @@ -2699,6 +2735,21 @@ static zend_never_inline uint8_t slow_index_convert_w(HashTable *ht, const zval ZEND_FALLTHROUGH; } case IS_NULL: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { + if (!GC_REFCOUNT(ht)) { + zend_array_destroy(ht); + } + return IS_NULL; + } + if (EG(exception)) { + return IS_NULL; + } value->str = ZSTR_EMPTY_ALLOC(); return IS_STRING; case IS_DOUBLE: @@ -3005,7 +3056,7 @@ static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_UNSET(z zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET EXECUTE_DATA_CC); } -static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, bool is_list, int slow EXECUTE_DATA_DC) +static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, bool is_list, bool slow EXECUTE_DATA_DC) { zval *retval; @@ -3143,6 +3194,9 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { ZVAL_UNDEFINED_OP2(); } + if (is_list && Z_TYPE_P(container) > IS_NULL) { + zend_error(E_WARNING, "Cannot use %s as array", zend_zval_type_name(container)); + } if (!is_list && type != BP_VAR_IS) { zend_error(E_WARNING, "Trying to access array offset on %s", zend_zval_value_name(container)); @@ -3189,7 +3243,22 @@ static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable num_idx: return zend_hash_index_find(ht, hval); } else if (Z_TYPE_P(offset) == IS_NULL) { -str_idx: +null_undef_idx: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return NULL; + } + + if (EG(exception)) { + return NULL; + } + return zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); } else if (Z_TYPE_P(offset) == IS_FALSE) { hval = 0; @@ -3203,7 +3272,7 @@ static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable goto num_idx; } else if (/*OP2_TYPE == IS_CV &&*/ Z_TYPE_P(offset) == IS_UNDEF) { ZVAL_UNDEFINED_OP2(); - goto str_idx; + goto null_undef_idx; } else { zend_illegal_array_offset_isset(offset); return NULL; @@ -3324,6 +3393,9 @@ static zend_never_inline bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable } else if (Z_TYPE_P(key) <= IS_NULL) { if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); + } else { + ZEND_ASSERT(Z_TYPE_P(key) == IS_NULL); + zend_error(E_DEPRECATED, "Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead"); } str = ZSTR_EMPTY_ALLOC(); goto str_key; @@ -4123,15 +4195,6 @@ static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DAT } } -static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_clone_call(zend_function *clone, zend_class_entry *scope) -{ - zend_throw_error(NULL, "Call to %s %s::__clone() from %s%s", - zend_visibility_string(clone->common.fn_flags), ZSTR_VAL(clone->common.scope->name), - scope ? "scope " : "global scope", - scope ? ZSTR_VAL(scope->name) : "" - ); -} - #if ZEND_INTENSIVE_DEBUGGING #define CHECK_SYMBOL_TABLES() \ @@ -5220,7 +5283,7 @@ static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval } } else if (UNEXPECTED(EG(exception))) { break; - } else if (UNEXPECTED(strlen(ZSTR_VAL(inc_filename)) != ZSTR_LEN(inc_filename))) { + } else if (UNEXPECTED(zend_str_has_nul_byte(inc_filename))) { zend_message_dispatcher( (type == ZEND_INCLUDE_ONCE) ? ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN, @@ -5254,7 +5317,7 @@ static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval break; case ZEND_INCLUDE: case ZEND_REQUIRE: - if (UNEXPECTED(strlen(ZSTR_VAL(inc_filename)) != ZSTR_LEN(inc_filename))) { + if (UNEXPECTED(zend_str_has_nul_byte(inc_filename))) { zend_message_dispatcher( (type == ZEND_INCLUDE) ? ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN, @@ -5377,7 +5440,12 @@ static zend_never_inline zend_result ZEND_FASTCALL zend_quick_check_constant( static zend_always_inline uint32_t zend_get_arg_offset_by_name( zend_function *fbc, zend_string *arg_name, void **cache_slot) { - if (EXPECTED(*cache_slot == fbc)) { + /* Due to closures, the `fbc` address isn't unique if the memory address is reused. + * The argument info will be however and uniquely positions the arguments. + * We do support NULL arg_info, so we have to distinguish that from an uninitialized cache slot. */ + void *unique_id = (void *) ((uintptr_t) fbc->common.arg_info | 1); + + if (EXPECTED(*cache_slot == unique_id)) { return *(uintptr_t *)(cache_slot + 1); } @@ -5388,8 +5456,10 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name( for (uint32_t i = 0; i < num_args; i++) { zend_arg_info *arg_info = &fbc->op_array.arg_info[i]; if (zend_string_equals(arg_name, arg_info->name)) { - *cache_slot = fbc; - *(uintptr_t *)(cache_slot + 1) = i; + if (!fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE)) { + *cache_slot = unique_id; + *(uintptr_t *)(cache_slot + 1) = i; + } return i; } } @@ -5399,7 +5469,7 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name( zend_internal_arg_info *arg_info = &fbc->internal_function.arg_info[i]; size_t len = strlen(arg_info->name); if (zend_string_equals_cstr(arg_name, arg_info->name, len)) { - *cache_slot = fbc; + *cache_slot = unique_id; *(uintptr_t *)(cache_slot + 1) = i; return i; } @@ -5407,8 +5477,10 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name( } if (fbc->common.fn_flags & ZEND_ACC_VARIADIC) { - *cache_slot = fbc; - *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args; + if (fbc->type == ZEND_INTERNAL_FUNCTION || !fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE)) { + *cache_slot = unique_id; + *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args; + } return fbc->common.num_args; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index cf15c9e3b2db5..13fb1ab7667a3 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -66,6 +66,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_functi ZEND_API ZEND_COLD void ZEND_FASTCALL zend_nodiscard_function(const zend_function *fbc); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_constant(const zend_constant *c, const zend_string *constant_name); +ZEND_API ZEND_COLD void zend_use_of_deprecated_trait(zend_class_entry *trait, const zend_string *used_by); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void); ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 9a7803e44e66e..91b8c5ab210ef 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -438,6 +438,12 @@ void shutdown_executor(void) /* {{{ */ zval *zv; #if ZEND_DEBUG bool fast_shutdown = 0; +#elif defined(__SANITIZE_ADDRESS__) + char *force_fast_shutdown = getenv("ZEND_ASAN_FORCE_FAST_SHUTDOWN"); + bool fast_shutdown = ( + is_zend_mm() + || (force_fast_shutdown && ZEND_ATOL(force_fast_shutdown)) + ) && !EG(full_tables_cleanup); #else bool fast_shutdown = is_zend_mm() && !EG(full_tables_cleanup); #endif @@ -808,7 +814,6 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ zend_function *func; uint32_t call_info; void *object_or_called_scope; - zend_class_entry *orig_fake_scope; ZVAL_UNDEF(fci->retval); @@ -997,7 +1002,7 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_ fci_cache->function_handler = NULL; } - orig_fake_scope = EG(fake_scope); + const zend_class_entry *orig_fake_scope = EG(fake_scope); EG(fake_scope) = NULL; if (func->type == ZEND_USER_FUNCTION) { uint32_t orig_jit_trace_num = EG(jit_trace_num); @@ -1125,22 +1130,20 @@ ZEND_API zend_result zend_call_method_if_exists( zend_object *object, zend_string *method_name, zval *retval, uint32_t param_count, zval *params) { - zend_fcall_info fci; - fci.size = sizeof(zend_fcall_info); - fci.object = object; - ZVAL_STR(&fci.function_name, method_name); - fci.retval = retval; - fci.param_count = param_count; - fci.params = params; - fci.named_params = NULL; - + zval zval_method; zend_fcall_info_cache fcc; - if (!zend_is_callable_ex(&fci.function_name, fci.object, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL)) { + + ZVAL_STR(&zval_method, method_name); + + if (UNEXPECTED(!zend_is_callable_ex(&zval_method, object, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL))) { ZVAL_UNDEF(retval); return FAILURE; } - return zend_call_function(&fci, &fcc); + zend_call_known_fcc(&fcc, retval, param_count, params, NULL); + /* Need to free potential trampoline (__call/__callStatic) copied function handler before releasing the closure */ + zend_release_fcall_info_cache(&fcc); + return SUCCESS; } /* 0-9 a-z A-Z _ \ 0x80-0xff */ @@ -1577,7 +1580,9 @@ static void zend_set_timeout_ex(zend_long seconds, bool reset_signals) /* {{{ */ return; } #elif defined(ZEND_MAX_EXECUTION_TIMERS) - zend_max_execution_timer_settime(seconds); + if (seconds > 0) { + zend_max_execution_timer_settime(seconds); + } if (reset_signals) { sigset_t sigset; @@ -1664,7 +1669,9 @@ void zend_unset_timeout(void) /* {{{ */ tq_timer = NULL; } #elif defined(ZEND_MAX_EXECUTION_TIMERS) - zend_max_execution_timer_settime(0); + if (EG(timeout_seconds)) { + zend_max_execution_timer_settime(0); + } #elif defined(HAVE_SETITIMER) if (EG(timeout_seconds)) { struct itimerval no_timeout; diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 8da55fcd48f66..e15f97ecfe802 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -172,7 +172,9 @@ #define GC_IDX2PTR(idx) (GC_G(buf) + (idx)) #define GC_PTR2IDX(ptr) ((ptr) - GC_G(buf)) +/* Get the value to be placed in an unused buffer entry with the specified next unused list index */ #define GC_IDX2LIST(idx) ((void*)(uintptr_t)(((idx) * sizeof(void*)) | GC_UNUSED)) +/* Get the index of the next item in the unused list from the given root buffer entry. */ #define GC_LIST2IDX(list) (((uint32_t)(uintptr_t)(list)) / sizeof(void*)) /* GC buffers */ @@ -228,10 +230,16 @@ } while (0) /* unused buffers */ + +/* Are there any unused root buffer entries? */ #define GC_HAS_UNUSED() \ (GC_G(unused) != GC_INVALID) + +/* Get the next unused entry and remove it from the list */ #define GC_FETCH_UNUSED() \ gc_fetch_unused() + +/* Add a root buffer entry to the unused list */ #define GC_LINK_UNUSED(root) \ gc_link_unused(root) @@ -244,12 +252,23 @@ ZEND_API int (*gc_collect_cycles)(void); +/* The type of a root buffer entry. + * + * The lower two bits are used for flags and need to be masked out to + * reconstruct a pointer. + * + * When a node in the root buffer is removed, the non-flag bits of the + * unused entry are used to store the index of the next entry in the unused + * list. */ typedef struct _gc_root_buffer { zend_refcounted *ref; } gc_root_buffer; typedef struct _zend_gc_globals { - gc_root_buffer *buf; /* preallocated arrays of buffers */ + /* The root buffer, which stores possible roots of reference cycles. It is + * also used to store garbage to be collected at the end of a run. + * A single array which is reallocated as necessary. */ + gc_root_buffer *buf; bool gc_enabled; bool gc_active; /* GC currently running, forbid nested GC */ @@ -262,13 +281,13 @@ typedef struct _zend_gc_globals { uint32_t buf_size; /* size of the GC buffer */ uint32_t num_roots; /* number of roots in GC buffer */ - uint32_t gc_runs; - uint32_t collected; + uint32_t gc_runs; /* number of GC runs since reset */ + uint32_t collected; /* number of collected nodes since reset */ - zend_hrtime_t activated_at; - zend_hrtime_t collector_time; - zend_hrtime_t dtor_time; - zend_hrtime_t free_time; + zend_hrtime_t activated_at; /* the timestamp of the last reset */ + zend_hrtime_t collector_time; /* time spent running GC (ns) */ + zend_hrtime_t dtor_time; /* time spent calling destructors (ns) */ + zend_hrtime_t free_time; /* time spent destroying nodes and freeing memory (ns) */ uint32_t dtor_idx; /* root buffer index */ uint32_t dtor_end; @@ -313,6 +332,7 @@ static zend_gc_globals gc_globals; typedef struct _gc_stack gc_stack; +/* The stack used for graph traversal is stored as a linked list of segments */ struct _gc_stack { gc_stack *prev; gc_stack *next; @@ -375,6 +395,11 @@ static void gc_stack_free(gc_stack *stack) } } +/* Map a full index to a compressed index. + * + * The root buffer can have up to 2^30 entries, but we only have 20 bits to + * store the index. So we use the 1<<19 bit as a compression flag and use the + * other 19 bits to store the index modulo 2^19. */ static zend_always_inline uint32_t gc_compress(uint32_t idx) { if (EXPECTED(idx < GC_MAX_UNCOMPRESSED)) { @@ -383,6 +408,9 @@ static zend_always_inline uint32_t gc_compress(uint32_t idx) return (idx % GC_MAX_UNCOMPRESSED) | GC_MAX_UNCOMPRESSED; } +/* Find the root buffer entry given a pointer and a compressed index. + * Iterate through the root buffer in steps of 2^19 until the pointer + * matches. */ static zend_always_inline gc_root_buffer* gc_decompress(zend_refcounted *ref, uint32_t idx) { gc_root_buffer *root = GC_IDX2PTR(idx); @@ -401,6 +429,8 @@ static zend_always_inline gc_root_buffer* gc_decompress(zend_refcounted *ref, ui } } +/* Get the index of the next unused root buffer entry, and remove it from the + * unused list. GC_HAS_UNUSED() must be true before calling this. */ static zend_always_inline uint32_t gc_fetch_unused(void) { uint32_t idx; @@ -414,6 +444,7 @@ static zend_always_inline uint32_t gc_fetch_unused(void) return idx; } +/* Add a root buffer entry to the unused list */ static zend_always_inline void gc_link_unused(gc_root_buffer *root) { root->ref = GC_IDX2LIST(GC_G(unused)); @@ -463,6 +494,7 @@ static void gc_trace_ref(zend_refcounted *ref) { } #endif +/* Mark a root buffer entry unused */ static zend_always_inline void gc_remove_from_roots(gc_root_buffer *root) { GC_LINK_UNUSED(root); @@ -565,6 +597,8 @@ void gc_reset(void) GC_G(activated_at) = zend_hrtime(); } +/* Enable/disable the garbage collector. + * Initialize globals if necessary. */ ZEND_API bool gc_enable(bool enable) { bool old_enabled = GC_G(gc_enabled); @@ -584,6 +618,7 @@ ZEND_API bool gc_enabled(void) return GC_G(gc_enabled); } +/* Protect the GC root buffer (prevent additions) */ ZEND_API bool gc_protect(bool protect) { bool old_protected = GC_G(gc_protected); @@ -621,6 +656,7 @@ static void gc_grow_root_buffer(void) GC_G(buf_size) = new_size; } +/* Adjust the GC activation threshold given the number of nodes collected by the last run */ static void gc_adjust_threshold(int count) { uint32_t new_threshold; @@ -651,6 +687,7 @@ static void gc_adjust_threshold(int count) } } +/* Perform a GC run and then add a node as a possible root. */ static zend_never_inline void ZEND_FASTCALL gc_possible_root_when_full(zend_refcounted *ref) { uint32_t idx; @@ -695,6 +732,8 @@ static zend_never_inline void ZEND_FASTCALL gc_possible_root_when_full(zend_refc GC_BENCH_PEAK(root_buf_peak, root_buf_length); } +/* Add a possible root node to the buffer. + * Maybe perform a GC run. */ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref) { uint32_t idx; @@ -731,6 +770,7 @@ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref) GC_BENCH_PEAK(root_buf_peak, root_buf_length); } +/* Add an extra root during a GC run */ static void ZEND_FASTCALL gc_extra_root(zend_refcounted *ref) { uint32_t idx; @@ -764,6 +804,7 @@ static void ZEND_FASTCALL gc_extra_root(zend_refcounted *ref) GC_BENCH_PEAK(root_buf_peak, root_buf_length); } +/* Remove a node from the root buffer given its compressed index */ static zend_never_inline void ZEND_FASTCALL gc_remove_compressed(zend_refcounted *ref, uint32_t idx) { gc_root_buffer *root = gc_decompress(ref, idx); @@ -793,6 +834,10 @@ ZEND_API void ZEND_FASTCALL gc_remove_from_buffer(zend_refcounted *ref) gc_remove_from_roots(root); } +/* Mark all nodes reachable from ref as black (live). Restore the reference + * counts decremented by gc_mark_grey(). See ScanBlack() in Bacon & Rajan. + * To implement a depth-first search, discovered nodes are added to a stack + * which is processed iteratively. */ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack) { HashTable *ht; @@ -992,6 +1037,8 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack) } } +/* Traverse the graph of nodes referred to by ref. Decrement the reference + * counts and mark visited nodes grey. See MarkGray() in Bacon & Rajan. */ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) { HashTable *ht; @@ -1204,6 +1251,9 @@ static void gc_compact(void) } } +/* For all roots marked purple, traverse the graph, decrementing the reference + * count of their child nodes. Mark visited nodes grey so that they are not + * visited again. See MarkRoots() in Bacon & Rajan. */ static void gc_mark_roots(gc_stack *stack) { gc_root_buffer *current, *last; @@ -1223,6 +1273,10 @@ static void gc_mark_roots(gc_stack *stack) } } +/* Traverse the reference graph of ref. Evaluate grey nodes and mark them + * black (to keep) or white (to free). Note that nodes initially marked white + * may later become black if they are visited from a live node. + * See Scan() in Bacon & Rajan. */ static void gc_scan(zend_refcounted *ref, gc_stack *stack) { HashTable *ht; @@ -1376,6 +1430,7 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack) } } +/* Scan all roots, coloring grey nodes black or white */ static void gc_scan_roots(gc_stack *stack) { uint32_t idx, end; @@ -1409,6 +1464,8 @@ static void gc_scan_roots(gc_stack *stack) } } +/* Add a node to the buffer with the garbage flag, so that it will be + * destroyed and freed when the scan is complete. */ static void gc_add_garbage(zend_refcounted *ref) { uint32_t idx; @@ -1434,6 +1491,7 @@ static void gc_add_garbage(zend_refcounted *ref) GC_G(num_roots)++; } +/* Traverse the reference graph from ref, marking any white nodes as garbage. */ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *stack) { int count = 0; @@ -1622,6 +1680,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta return count; } +/* Traverse the reference graph from all roots, marking white nodes as garbage. */ static int gc_collect_roots(uint32_t *flags, gc_stack *stack) { uint32_t idx, end; @@ -1808,6 +1867,7 @@ static ZEND_COLD ZEND_NORETURN void gc_start_destructor_fiber_error(void) zend_error_noreturn(E_ERROR, "Unable to start destructor fiber"); } +/* Call destructors for garbage in the buffer. */ static zend_always_inline zend_result gc_call_destructors(uint32_t idx, uint32_t end, zend_fiber *fiber) { gc_root_buffer *current; @@ -1910,6 +1970,7 @@ static zend_never_inline void gc_call_destructors_in_fiber(uint32_t end) } } +/* Perform a garbage collection run. The default implementation of gc_collect_cycles. */ ZEND_API int zend_gc_collect_cycles(void) { int total_count = 0; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a6ea91a7425b9..22f6048040b30 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -498,8 +498,14 @@ ZEND_API zend_execute_data *zend_generator_check_placeholder_frame(zend_execute_ return ptr; } -static void zend_generator_throw_exception(zend_generator *generator, zval *exception) +static zend_result zend_generator_throw_exception(zend_generator *generator, zval *exception) { + if (generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING) { + zval_ptr_dtor(exception); + zend_throw_error(NULL, "Cannot resume an already running generator"); + return FAILURE; + } + zend_execute_data *original_execute_data = EG(current_execute_data); /* Throw the exception in the context of the generator. Decrementing the opline @@ -520,6 +526,8 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce } EG(current_execute_data) = original_execute_data; + + return SUCCESS; } static void zend_generator_add_child(zend_generator *generator, zend_generator *child) @@ -786,6 +794,8 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ orig_generator->execute_fake.prev_execute_data = original_execute_data; } + generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING; + /* Ensure this is run after executor_data swap to have a proper stack trace */ if (UNEXPECTED(!Z_ISUNDEF(generator->values))) { if (EXPECTED(zend_generator_get_next_delegated_value(generator) == SUCCESS)) { @@ -794,7 +804,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ EG(jit_trace_num) = original_jit_trace_num; orig_generator->flags &= ~(ZEND_GENERATOR_DO_INIT | ZEND_GENERATOR_IN_FIBER); - generator->flags &= ~ZEND_GENERATOR_IN_FIBER; + generator->flags &= ~(ZEND_GENERATOR_CURRENTLY_RUNNING | ZEND_GENERATOR_IN_FIBER); return; } /* If there are no more delegated values, resume the generator @@ -817,7 +827,6 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ * account for the following increment */ || (generator->flags & ZEND_GENERATOR_FORCED_CLOSE)); generator->execute_data->opline++; - generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING; if (!ZEND_OBSERVER_ENABLED) { zend_execute_ex(generator->execute_data); } else { @@ -1025,7 +1034,9 @@ ZEND_METHOD(Generator, throw) if (generator->execute_data) { zend_generator *root = zend_generator_get_current(generator); - zend_generator_throw_exception(root, exception); + if (zend_generator_throw_exception(root, exception) == FAILURE) { + return; + } zend_generator_resume(generator); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 079bfb99caccf..48b978b535014 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -198,7 +198,7 @@ struct _zend_executor_globals { size_t vm_stack_page_size; struct _zend_execute_data *current_execute_data; - zend_class_entry *fake_scope; /* used to avoid checks accessing properties */ + const zend_class_entry *fake_scope; /* used to avoid checks accessing properties */ uint32_t jit_trace_num; /* Used by tracing JIT to reference the currently running trace */ @@ -295,7 +295,8 @@ struct _zend_executor_globals { size_t fiber_stack_size; /* If record_errors is enabled, all emitted diagnostics will be recorded, - * in addition to being processed as usual. */ + * and their processing is delayed until zend_emit_recorded_errors() + * is called or a fatal diagnostic is emitted. */ bool record_errors; uint32_t num_errors; zend_error_info **errors; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 66cfb250d1fec..d460c40b79714 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -634,8 +634,15 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval && EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { HT_DEC_ITERATORS_COUNT(iter->ht); } - SEPARATE_ARRAY(array); - ht = Z_ARRVAL_P(array); + + /* Inlined SEPARATE_ARRAY() with updating of iterator when EG(ht_iterators) grows. */ + if (UNEXPECTED(GC_REFCOUNT(ht) > 1)) { + ZVAL_ARR(array, zend_array_dup(ht)); + GC_TRY_DELREF(ht); + iter = EG(ht_iterators) + idx; + ht = Z_ARRVAL_P(array); + } + if (EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { HT_INC_ITERATORS_COUNT(ht); } @@ -1378,7 +1385,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht) q->key = p->key; Z_NEXT(q->val) = HT_HASH(ht, nIndex); HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j); - if (UNEXPECTED(ht->nInternalPointer == i)) { + if (UNEXPECTED(ht->nInternalPointer > j && ht->nInternalPointer <= i)) { ht->nInternalPointer = j; } q++; @@ -1397,7 +1404,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_rehash(HashTable *ht) q->key = p->key; Z_NEXT(q->val) = HT_HASH(ht, nIndex); HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j); - if (UNEXPECTED(ht->nInternalPointer == i)) { + if (UNEXPECTED(ht->nInternalPointer > j && ht->nInternalPointer <= i)) { ht->nInternalPointer = j; } if (UNEXPECTED(i >= iter_pos)) { @@ -2842,7 +2849,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_hash_move_backwards_ex(const HashTable * /* This function should be made binary safe */ -ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, const HashPosition *pos) +ZEND_API zend_hash_key_type ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, const HashPosition *pos) { uint32_t idx; Bucket *p; @@ -2889,7 +2896,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *h } } -ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(const HashTable *ht, const HashPosition *pos) +ZEND_API zend_hash_key_type ZEND_FASTCALL zend_hash_get_current_key_type_ex(const HashTable *ht, const HashPosition *pos) { uint32_t idx; Bucket *p; diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index b2aaecce0d27c..71206e61550bb 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -26,9 +26,11 @@ #include "zend_string.h" #include "zend_sort.h" -#define HASH_KEY_IS_STRING 1 -#define HASH_KEY_IS_LONG 2 -#define HASH_KEY_NON_EXISTENT 3 +typedef enum { + HASH_KEY_IS_STRING = 1, + HASH_KEY_IS_LONG, + HASH_KEY_NON_EXISTENT +} zend_hash_key_type; #define HASH_UPDATE (1<<0) /* Create new entry, or update the existing one. */ #define HASH_ADD (1<<1) /* Create new entry, or fail if it exists. */ @@ -251,9 +253,9 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_current_pos(const HashTable *h ZEND_API zend_result ZEND_FASTCALL zend_hash_move_forward_ex(const HashTable *ht, HashPosition *pos); ZEND_API zend_result ZEND_FASTCALL zend_hash_move_backwards_ex(const HashTable *ht, HashPosition *pos); -ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, const HashPosition *pos); +ZEND_API zend_hash_key_type ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, const HashPosition *pos); ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, const HashPosition *pos); -ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(const HashTable *ht, const HashPosition *pos); +ZEND_API zend_hash_key_type ZEND_FASTCALL zend_hash_get_current_key_type_ex(const HashTable *ht, const HashPosition *pos); ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(const HashTable *ht, const HashPosition *pos); ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(const HashTable *ht, HashPosition *pos); ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(const HashTable *ht, HashPosition *pos); @@ -270,13 +272,13 @@ static zend_always_inline zend_result zend_hash_move_forward(HashTable *ht) { static zend_always_inline zend_result zend_hash_move_backwards(HashTable *ht) { return zend_hash_move_backwards_ex(ht, &ht->nInternalPointer); } -static zend_always_inline int zend_hash_get_current_key(const HashTable *ht, zend_string **str_index, zend_ulong *num_index) { +static zend_always_inline zend_hash_key_type zend_hash_get_current_key(const HashTable *ht, zend_string **str_index, zend_ulong *num_index) { return zend_hash_get_current_key_ex(ht, str_index, num_index, &ht->nInternalPointer); } static zend_always_inline void zend_hash_get_current_key_zval(const HashTable *ht, zval *key) { zend_hash_get_current_key_zval_ex(ht, key, &ht->nInternalPointer); } -static zend_always_inline int zend_hash_get_current_key_type(const HashTable *ht) { +static zend_always_inline zend_hash_key_type zend_hash_get_current_key_type(const HashTable *ht) { return zend_hash_get_current_key_type_ex(ht, &ht->nInternalPointer); } static zend_always_inline zval* zend_hash_get_current_data(const HashTable *ht) { diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index d27cca5b76187..89e51cb7f0754 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1085,10 +1085,7 @@ static void ZEND_COLD emit_incompatible_method_error( "Return type of %s should either be compatible with %s, " "or the #[\\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice", ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype)); - if (EG(exception)) { - zend_exception_uncaught_error( - "During inheritance of %s", ZSTR_VAL(parent_scope->name)); - } + ZEND_ASSERT(!EG(exception)); } } else { zend_error_at(E_COMPILE_ERROR, func_filename(child), func_lineno(child), @@ -1566,6 +1563,10 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke ZSTR_VAL(key), ZSTR_VAL(parent_info->ce->name)); } + + if (child_info->ce == ce) { + child_info->flags &= ~ZEND_ACC_OVERRIDE; + } } } else { zend_function **hooks = parent_info->hooks; @@ -1713,10 +1714,25 @@ void zend_build_properties_info_table(zend_class_entry *ce) } } - ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&ce->properties_info, zend_string *key, prop) { if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0 && !(prop->flags & ZEND_ACC_VIRTUAL)) { - uint32_t prop_table_offset = OBJ_PROP_TO_NUM(!(prop->prototype->flags & ZEND_ACC_VIRTUAL) ? prop->prototype->offset : prop->offset); + const zend_property_info *root_prop = prop->prototype; + if (UNEXPECTED(root_prop->flags & ZEND_ACC_VIRTUAL)) { + /* Prototype is virtual, we need to manually hunt down the first backed property. */ + root_prop = prop; + zend_class_entry *parent_ce; + while ((parent_ce = root_prop->ce->parent)) { + zend_property_info *parent_prop = zend_hash_find_ptr(&parent_ce->properties_info, key); + if (!parent_prop + || parent_prop->prototype != prop->prototype + || (parent_prop->flags & ZEND_ACC_VIRTUAL)) { + break; + } + root_prop = parent_prop; + } + } + uint32_t prop_table_offset = OBJ_PROP_TO_NUM(root_prop->offset); table[prop_table_offset] = prop; } } ZEND_HASH_FOREACH_END(); @@ -2303,13 +2319,11 @@ static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry void zend_inheritance_check_override(const zend_class_entry *ce) { - zend_function *f; - if (ce->ce_flags & ZEND_ACC_TRAIT) { return; } - ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, f) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, zend_function *f) { if (f->common.fn_flags & ZEND_ACC_OVERRIDE) { ZEND_ASSERT(f->type != ZEND_INTERNAL_FUNCTION); @@ -2320,14 +2334,17 @@ void zend_inheritance_check_override(const zend_class_entry *ce) } } ZEND_HASH_FOREACH_END(); - if (ce->num_hooked_props) { - zend_property_info *prop; - ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { - if (!prop->hooks) { - continue; - } + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, zend_property_info *prop) { + if (prop->flags & ZEND_ACC_OVERRIDE) { + zend_error_noreturn( + E_COMPILE_ERROR, + "%s::$%s has #[\\Override] attribute, but no matching parent property exists", + ZSTR_VAL(ce->name), zend_get_unmangled_property_name(prop->name)); + } + + if (prop->hooks) { for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { - f = prop->hooks[i]; + zend_function *f = prop->hooks[i]; if (f && f->common.fn_flags & ZEND_ACC_OVERRIDE) { ZEND_ASSERT(f->type != ZEND_INTERNAL_FUNCTION); @@ -2337,8 +2354,8 @@ void zend_inheritance_check_override(const zend_class_entry *ce) ZEND_FN_SCOPE_NAME(f), ZSTR_VAL(f->common.function_name)); } } - } ZEND_HASH_FOREACH_END(); - } + } + } ZEND_HASH_FOREACH_END(); } @@ -3507,6 +3524,13 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string free_alloca(traits_and_interfaces, use_heap); return NULL; } + if (UNEXPECTED(trait->ce_flags & ZEND_ACC_DEPRECATED)) { + zend_use_of_deprecated_trait(trait, ce->name); + if (UNEXPECTED(EG(exception))) { + free_alloca(traits_and_interfaces, use_heap); + return NULL; + } + } for (j = 0; j < i; j++) { if (traits_and_interfaces[j] == trait) { /* skip duplications */ @@ -3546,8 +3570,6 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string } #endif - bool orig_record_errors = EG(record_errors); - if (ce->ce_flags & ZEND_ACC_IMMUTABLE && is_cacheable) { if (zend_inheritance_cache_get && zend_inheritance_cache_add) { zend_class_entry *ret = zend_inheritance_cache_get(ce, parent, traits_and_interfaces); @@ -3559,16 +3581,21 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string Z_CE_P(zv) = ret; return ret; } - - /* Make sure warnings (such as deprecations) thrown during inheritance - * will be recorded in the inheritance cache. */ - zend_begin_record_errors(); } else { is_cacheable = 0; } proto = ce; } + /* Delay and record warnings (such as deprecations) thrown during + * inheritance, so they will be recorded in the inheritance cache. + * Warnings must be delayed in all cases so that we get a consistent + * behavior regardless of cacheability. */ + bool orig_record_errors = EG(record_errors); + if (!orig_record_errors) { + zend_begin_record_errors(); + } + zend_try { if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { /* Lazy class loading */ @@ -3759,6 +3786,7 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string } if (!orig_record_errors) { + zend_emit_recorded_errors(); zend_free_recorded_errors(); } if (traits_and_interfaces) { @@ -3919,10 +3947,12 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_ orig_linking_class = CG(current_linking_class); CG(current_linking_class) = is_cacheable ? ce : NULL; + bool orig_record_errors = EG(record_errors); + zend_try{ CG(zend_lineno) = ce->info.user.line_start; - if (is_cacheable) { + if (!orig_record_errors) { zend_begin_record_errors(); } @@ -3944,13 +3974,13 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_ CG(current_linking_class) = orig_linking_class; } zend_catch { - EG(record_errors) = false; - zend_free_recorded_errors(); + if (!orig_record_errors) { + EG(record_errors) = false; + zend_free_recorded_errors(); + } zend_bailout(); } zend_end_try(); - EG(record_errors) = false; - if (is_cacheable) { HashTable *ht = (HashTable*)ce->inheritance_cache; zend_class_entry *new_ce; @@ -3968,6 +3998,11 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_ } } + if (!orig_record_errors) { + zend_emit_recorded_errors(); + zend_free_recorded_errors(); + } + if (ZSTR_HAS_CE_CACHE(ce->name)) { ZSTR_SET_CE_CACHE(ce->name, ce); } diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 199ebfb2e9b45..689e76794df34 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -248,10 +248,16 @@ ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_ zend_unregister_ini_entries_ex(module_number, module_type); return FAILURE; } + + zend_string *prev_value = p->value; + if (((default_value = zend_get_configuration_directive(p->name)) != NULL) && (!p->on_modify || p->on_modify(p, Z_STR_P(default_value), p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP) == SUCCESS)) { - p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value))); + /* Skip assigning the value if the handler has already done so. */ + if (p->value == prev_value) { + p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value))); + } } else { p->value = ini_entry->value ? zend_string_init_interned(ini_entry->value, ini_entry->value_length, 1) : NULL; @@ -389,14 +395,20 @@ ZEND_API zend_result zend_alter_ini_entry_ex(zend_string *name, zend_string *new zend_hash_add_ptr(EG(modified_ini_directives), ini_entry->name, ini_entry); } + zend_string *prev_value = ini_entry->value; duplicate = zend_string_copy(new_value); if (!ini_entry->on_modify || ini_entry->on_modify(ini_entry, duplicate, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) { - if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */ - zend_string_release(ini_entry->value); + if (modified && ini_entry->orig_value != prev_value) { /* we already changed the value, free the changed value */ + zend_string_release(prev_value); + } + /* Skip assigning the value if the handler has already done so. */ + if (ini_entry->value == prev_value) { + ini_entry->value = duplicate; + } else { + zend_string_release(duplicate); } - ini_entry->value = duplicate; } else { zend_string_release(duplicate); return FAILURE; diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index 07df7be88e8c0..5f788f152fb6a 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -353,7 +353,7 @@ static void normalize_value(zval *zv) %left '|' '&' '^' %precedence '~' '!' -%destructor { zval_ini_dtor(&$$); } TC_RAW TC_CONSTANT TC_NUMBER TC_STRING TC_WHITESPACE TC_LABEL TC_OFFSET TC_VARNAME BOOL_TRUE BOOL_FALSE NULL_NULL cfg_var_ref constant_literal constant_string encapsed_list expr option_offset section_string_or_value string_or_value var_string_list var_string_list_section +%destructor { zval_ini_dtor(&$$); } TC_RAW TC_CONSTANT TC_NUMBER TC_STRING TC_WHITESPACE TC_LABEL TC_OFFSET TC_VARNAME BOOL_TRUE BOOL_FALSE NULL_NULL cfg_var_ref constant_literal constant_string encapsed_list expr fallback option_offset section_string_or_value string_or_value var_string_list var_string_list_section %% diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l index 44159297a04e1..b87f4e33cc8f8 100644 --- a/Zend/zend_ini_scanner.l +++ b/Zend/zend_ini_scanner.l @@ -352,16 +352,16 @@ restart: /*!re2c re2c:yyfill:check = 0; LNUM [0-9]+ -DNUM ([0-9]*[\.][0-9]+)|([0-9]+[\.][0-9]*) +DNUM ([0-9]*[.][0-9]+)|([0-9]+[.][0-9]*) NUMBER [-]?{LNUM}|{DNUM} ANY_CHAR (.|[\n\t]) NEWLINE ("\r"|"\n"|"\r\n") TABS_AND_SPACES [ \t] WHITESPACE [ \t]+ CONSTANT [a-zA-Z_][a-zA-Z0-9_]* -LABEL_CHAR [^=\n\r\t;&|^$~(){}!"\[\]\x00] +LABEL_CHAR [^=\n\r\t;&|^$~(){}!"[\]\x00] LABEL ({LABEL_CHAR}+) -TOKENS [:,.\[\]"'()&|^+-/*=%$!~<>?@{}] +TOKENS [:,.[\]"'()&|^+-/*=%$!~<>?@{}] OPERATORS [&|^~()!] DOLLAR_CURLY "${" diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c index f67033b11161c..64dbb0541a80d 100644 --- a/Zend/zend_iterators.c +++ b/Zend/zend_iterators.c @@ -31,6 +31,7 @@ static const zend_object_handlers iterator_object_handlers = { iter_wrapper_free, iter_wrapper_dtor, NULL, /* clone_obj */ + NULL, /* clone_obj_with */ NULL, /* prop read */ NULL, /* prop write */ NULL, /* read dim */ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 016c6e5c9d098..e4d61006fe12f 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -212,7 +212,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_INC "'++'" %token T_DEC "'--'" %token T_INT_CAST "'(int)'" -%token T_DOUBLE_CAST "'(double)'" +%token T_DOUBLE_CAST "'(float)'" %token T_STRING_CAST "'(string)'" %token T_ARRAY_CAST "'(array)'" %token T_OBJECT_CAST "'(object)'" @@ -259,7 +259,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type unprefixed_use_declarations const_decl inner_statement %type expr optional_expr while_statement for_statement foreach_variable %type foreach_statement declare_statement finally_statement unset_variable variable -%type extends_from parameter optional_type_without_static argument global_var +%type extends_from parameter optional_type_without_static argument argument_no_expr global_var %type static_var class_statement trait_adaptation trait_precedence trait_alias %type absolute_trait_method_reference trait_method_reference property echo_expr %type new_dereferenceable new_non_dereferenceable anonymous_class class_name class_name_reference simple_variable @@ -287,7 +287,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type enum_declaration_statement enum_backing_type enum_case enum_case_expr %type function_name non_empty_member_modifiers %type property_hook property_hook_list optional_property_hook_list hooked_property property_hook_body -%type optional_parameter_list +%type optional_parameter_list clone_argument_list non_empty_clone_argument_list %type returns_ref function fn is_reference is_variadic property_modifiers property_hook_modifiers %type method_modifiers class_const_modifiers member_modifier optional_cpp_modifiers @@ -713,21 +713,20 @@ switch_case_list: case_list: %empty { $$ = zend_ast_create_list(0, ZEND_AST_SWITCH_LIST); } - | case_list T_CASE expr case_separator inner_statement_list + | case_list T_CASE expr ':' inner_statement_list { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, $3, $5)); } - | case_list T_DEFAULT case_separator inner_statement_list + | case_list T_CASE expr ';' inner_statement_list + { $$ = zend_ast_list_add($1, zend_ast_create_ex(ZEND_AST_SWITCH_CASE, ZEND_ALT_CASE_SYNTAX, $3, $5)); } + | case_list T_DEFAULT ':' inner_statement_list { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, NULL, $4)); } -; - -case_separator: - ':' - | ';' + | case_list T_DEFAULT ';' inner_statement_list + { $$ = zend_ast_list_add($1, zend_ast_create_ex(ZEND_AST_SWITCH_CASE, ZEND_ALT_CASE_SYNTAX, NULL, $4)); } ; match: T_MATCH '(' expr ')' '{' match_arm_list '}' - { $$ = zend_ast_create(ZEND_AST_MATCH, $3, $6); }; + { $$ = zend_ast_create(ZEND_AST_MATCH, $3, $6); } ; match_arm_list: @@ -914,13 +913,42 @@ non_empty_argument_list: { $$ = zend_ast_list_add($1, $3); } ; -argument: - expr { $$ = $1; } - | identifier ':' expr +/* `clone_argument_list` is necessary to resolve a parser ambiguity (shift-reduce conflict) + * of `clone($expr)`, which could either be parsed as a function call with `$expr` as the first + * argument or as a use of the `clone` language construct with an expression with useless + * parenthesis. Both would be valid and result in the same AST / the same semantics. + * `clone_argument_list` is defined in a way that an `expr` in the first position needs to + * be followed by a `,` which is not valid syntax for a parenthesized `expr`, ensuring + * that calling `clone()` with a single unnamed parameter is handled by the language construct + * syntax. + */ +clone_argument_list: + '(' ')' { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); } + | '(' non_empty_clone_argument_list possible_comma ')' { $$ = $2; } + | '(' expr ',' ')' { $$ = zend_ast_create_list(1, ZEND_AST_ARG_LIST, $2); } + | '(' T_ELLIPSIS ')' { $$ = zend_ast_create_fcc(); } +; + +non_empty_clone_argument_list: + expr ',' argument + { $$ = zend_ast_create_list(2, ZEND_AST_ARG_LIST, $1, $3); } + | argument_no_expr + { $$ = zend_ast_create_list(1, ZEND_AST_ARG_LIST, $1); } + | non_empty_clone_argument_list ',' argument + { $$ = zend_ast_list_add($1, $3); } +; + +argument_no_expr: + identifier ':' expr { $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, $3); } | T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); } ; +argument: + expr { $$ = $1; } + | argument_no_expr { $$ = $1; } +; + global_var_list: global_var_list ',' global_var { $$ = zend_ast_list_add($1, $3); } | global_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); } @@ -1228,10 +1256,10 @@ expr: { $$ = zend_ast_create(ZEND_AST_ASSIGN, $1, $3); } | variable '=' ampersand variable { $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); } - | T_CLONE '(' T_ELLIPSIS ')' { + | T_CLONE clone_argument_list { zend_ast *name = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_CLONE)); name->attr = ZEND_NAME_FQ; - $$ = zend_ast_create(ZEND_AST_CALL, name, zend_ast_create_fcc()); + $$ = zend_ast_create(ZEND_AST_CALL, name, $2); } | T_CLONE expr { zend_ast *name = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_CLONE)); @@ -1320,6 +1348,7 @@ expr: | '(' expr ')' { $$ = $2; if ($$->kind == ZEND_AST_CONDITIONAL) $$->attr = ZEND_PARENTHESIZED_CONDITIONAL; + if ($$->kind == ZEND_AST_ARROW_FUNC) $$->attr = ZEND_PARENTHESIZED_ARROW_FUNC; } | new_dereferenceable { $$ = $1; } | new_non_dereferenceable { $$ = $1; } diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 5e377249422a5..3ecb2f8d0ee45 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -210,6 +210,7 @@ void shutdown_scanner(void) zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); SCNG(heredoc_scan_ahead) = 0; SCNG(on_event) = NULL; + SCNG(on_event_context) = NULL; } ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state) @@ -581,6 +582,8 @@ ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle) zend_set_compiled_filename(compiled_filename); zend_string_release_ex(compiled_filename, 0); + SCNG(on_event) = NULL; + SCNG(on_event_context) = NULL; RESET_DOC_COMMENT(); CG(zend_lineno) = 1; CG(increment_lineno) = 0; @@ -650,7 +653,17 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type) } } } else { + bool orig_record_errors = EG(record_errors); + if (!orig_record_errors) { + zend_begin_record_errors(); + } + op_array = zend_compile(ZEND_USER_FUNCTION); + + if (!orig_record_errors) { + zend_emit_recorded_errors(); + zend_free_recorded_errors(); + } } zend_restore_lexical_state(&original_lex_state); @@ -756,6 +769,8 @@ ZEND_API void zend_prepare_string_for_scanning(zval *str, zend_string *filename) zend_set_compiled_filename(filename); CG(zend_lineno) = 1; CG(increment_lineno) = 0; + SCNG(on_event) = NULL; + SCNG(on_event_context) = NULL; RESET_DOC_COMMENT(); } @@ -911,7 +926,7 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter ZVAL_STRINGL(zendlval, yytext, yyleng); \ } -static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type) +static zend_result zend_scan_escape_string(zval *zendlval, char *str, size_t len, char quote_type) { char *s, *t; char *end; @@ -921,9 +936,7 @@ static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, c ZVAL_EMPTY_STRING(zendlval); } else { zend_uchar c = (zend_uchar)*str; - if (c == '\n' || c == '\r') { - CG(zend_lineno)++; - } + HANDLE_NEWLINE(c); ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c)); } goto skip_escape_conversion; @@ -1621,11 +1634,31 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN_WITH_IDENT(T_VAR); } -"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" { +"("{TABS_AND_SPACES}("int"){TABS_AND_SPACES}")" { + RETURN_TOKEN(T_INT_CAST); +} + +"("{TABS_AND_SPACES}("integer"){TABS_AND_SPACES}")" { + if (PARSER_MODE()) { + zend_error(E_DEPRECATED, "Non-canonical cast (integer) is deprecated, use the (int) cast instead"); + if (EG(exception)) { + RETURN_TOKEN(T_ERROR); + } + } RETURN_TOKEN(T_INT_CAST); } -"("{TABS_AND_SPACES}("double"|"float"){TABS_AND_SPACES}")" { +"("{TABS_AND_SPACES}("float"){TABS_AND_SPACES}")" { + RETURN_TOKEN(T_DOUBLE_CAST); +} + +"("{TABS_AND_SPACES}("double"){TABS_AND_SPACES}")" { + if (PARSER_MODE()) { + zend_error(E_DEPRECATED, "Non-canonical cast (double) is deprecated, use the (float) cast instead"); + if (EG(exception)) { + RETURN_TOKEN(T_ERROR); + } + } RETURN_TOKEN(T_DOUBLE_CAST); } @@ -1637,7 +1670,17 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN(T_DOUBLE_CAST); } -"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" { +"("{TABS_AND_SPACES}("string"){TABS_AND_SPACES}")" { + RETURN_TOKEN(T_STRING_CAST); +} + +"("{TABS_AND_SPACES}("binary"){TABS_AND_SPACES}")" { + if (PARSER_MODE()) { + zend_error(E_DEPRECATED, "Non-canonical cast (binary) is deprecated, use the (string) cast instead"); + if (EG(exception)) { + RETURN_TOKEN(T_ERROR); + } + } RETURN_TOKEN(T_STRING_CAST); } @@ -1649,7 +1692,17 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN(T_OBJECT_CAST); } -"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" { +"("{TABS_AND_SPACES}("bool"){TABS_AND_SPACES}")" { + RETURN_TOKEN(T_BOOL_CAST); +} + +"("{TABS_AND_SPACES}("boolean"){TABS_AND_SPACES}")" { + if (PARSER_MODE()) { + zend_error(E_DEPRECATED, "Non-canonical cast (boolean) is deprecated, use the (bool) cast instead"); + if (EG(exception)) { + RETURN_TOKEN(T_ERROR); + } + } RETURN_TOKEN(T_BOOL_CAST); } @@ -1817,11 +1870,11 @@ OPTIONAL_WHITESPACE_OR_COMMENTS ({WHITESPACE}|{MULTI_LINE_COMMENT}|{SINGLE_LINE_ RETURN_TOKEN(T_MUL_EQUAL); } -"*\*" { +"**" { RETURN_TOKEN(T_POW); } -"*\*=" { +"**=" { RETURN_TOKEN(T_POW_EQUAL); } @@ -2512,9 +2565,7 @@ inline_char_handler: ZVAL_EMPTY_STRING(zendlval); } else { zend_uchar c = (zend_uchar)*(yytext+bprefix+1); - if (c == '\n' || c == '\r') { - CG(zend_lineno)++; - } + HANDLE_NEWLINE(c); ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c)); } goto skip_escape_conversion; @@ -2707,6 +2758,7 @@ skip_escape_conversion: SCNG(heredoc_scan_ahead) = 1; SCNG(heredoc_indentation) = 0; SCNG(heredoc_indentation_uses_spaces) = 0; + SCNG(on_event_context) = NULL; LANG_SCNG(on_event) = NULL; CG(doc_comment) = NULL; diff --git a/Zend/zend_lazy_objects.c b/Zend/zend_lazy_objects.c index d1b950160e1cc..cf00804eda33b 100644 --- a/Zend/zend_lazy_objects.c +++ b/Zend/zend_lazy_objects.c @@ -93,7 +93,7 @@ void zend_lazy_objects_destroy(zend_lazy_objects_store *store) zend_hash_destroy(&store->infos); } -static void zend_lazy_object_set_info(zend_object *obj, zend_lazy_object_info *info) +static void zend_lazy_object_set_info(const zend_object *obj, zend_lazy_object_info *info) { ZEND_ASSERT(zend_object_is_lazy(obj)); @@ -102,7 +102,7 @@ static void zend_lazy_object_set_info(zend_object *obj, zend_lazy_object_info *i (void)zv; } -static zend_lazy_object_info* zend_lazy_object_get_info(zend_object *obj) +static zend_lazy_object_info* zend_lazy_object_get_info(const zend_object *obj) { ZEND_ASSERT(zend_object_is_lazy(obj)); @@ -112,7 +112,7 @@ static zend_lazy_object_info* zend_lazy_object_get_info(zend_object *obj) return info; } -static bool zend_lazy_object_has_stale_info(zend_object *obj) +static bool zend_lazy_object_has_stale_info(const zend_object *obj) { return zend_hash_index_find_ptr(&EG(lazy_objects_store).infos, obj->handle); } @@ -154,18 +154,18 @@ zend_object* zend_lazy_object_get_instance(zend_object *obj) return obj; } -zend_lazy_object_flags_t zend_lazy_object_get_flags(zend_object *obj) +zend_lazy_object_flags_t zend_lazy_object_get_flags(const zend_object *obj) { return zend_lazy_object_get_info(obj)->flags; } -void zend_lazy_object_del_info(zend_object *obj) +void zend_lazy_object_del_info(const zend_object *obj) { zend_result res = zend_hash_index_del(&EG(lazy_objects_store).infos, obj->handle); ZEND_ASSERT(res == SUCCESS); } -bool zend_lazy_object_decr_lazy_props(zend_object *obj) +bool zend_lazy_object_decr_lazy_props(const zend_object *obj) { ZEND_ASSERT(zend_object_is_lazy(obj)); ZEND_ASSERT(!zend_lazy_object_initialized(obj)); @@ -183,7 +183,7 @@ bool zend_lazy_object_decr_lazy_props(zend_object *obj) * Making objects lazy */ -ZEND_API bool zend_class_can_be_lazy(zend_class_entry *ce) +ZEND_API bool zend_class_can_be_lazy(const zend_class_entry *ce) { /* Internal classes are not supported */ if (UNEXPECTED(ce->type == ZEND_INTERNAL_CLASS && ce != zend_standard_class_def)) { @@ -444,7 +444,7 @@ static void zend_lazy_object_revert_init(zend_object *obj, zval *properties_tabl OBJ_EXTRA_FLAGS(obj) |= IS_OBJ_LAZY_UNINITIALIZED; } -static bool zend_lazy_object_compatible(zend_object *real_object, zend_object *lazy_object) +static bool zend_lazy_object_compatible(const zend_object *real_object, const zend_object *lazy_object) { if (EXPECTED(real_object->ce == lazy_object->ce)) { return true; diff --git a/Zend/zend_lazy_objects.h b/Zend/zend_lazy_objects.h index 64f68d66360cd..fc0a908e7ad2f 100644 --- a/Zend/zend_lazy_objects.h +++ b/Zend/zend_lazy_objects.h @@ -57,7 +57,7 @@ typedef struct _zend_property_info zend_property_info; typedef struct _zend_fcall_info zend_fcall_info; typedef struct _zend_fcall_info_cache zend_fcall_info_cache; -ZEND_API bool zend_class_can_be_lazy(zend_class_entry *ce); +ZEND_API bool zend_class_can_be_lazy(const zend_class_entry *ce); ZEND_API zend_object *zend_object_make_lazy(zend_object *obj, zend_class_entry *class_type, zval *initializer_zv, zend_fcall_info_cache *initializer_fcc, zend_lazy_object_flags_t flags); @@ -68,39 +68,39 @@ void zend_lazy_objects_init(zend_lazy_objects_store *store); void zend_lazy_objects_destroy(zend_lazy_objects_store *store); zval* zend_lazy_object_get_initializer_zv(zend_object *obj); zend_object *zend_lazy_object_get_instance(zend_object *obj); -zend_lazy_object_flags_t zend_lazy_object_get_flags(zend_object *obj); -void zend_lazy_object_del_info(zend_object *obj); +zend_lazy_object_flags_t zend_lazy_object_get_flags(const zend_object *obj); +void zend_lazy_object_del_info(const zend_object *obj); ZEND_API HashTable *zend_lazy_object_get_properties(zend_object *object); zend_object *zend_lazy_object_clone(zend_object *old_obj); HashTable *zend_lazy_object_debug_info(zend_object *object, int *is_temp); HashTable *zend_lazy_object_get_gc(zend_object *zobj, zval **table, int *n); -bool zend_lazy_object_decr_lazy_props(zend_object *obj); +bool zend_lazy_object_decr_lazy_props(const zend_object *obj); void zend_lazy_object_realize(zend_object *obj); ZEND_API zend_property_info *zend_lazy_object_get_property_info_for_slot(zend_object *obj, zval *slot); -static zend_always_inline bool zend_object_is_lazy(zend_object *obj) +static zend_always_inline bool zend_object_is_lazy(const zend_object *obj) { return (OBJ_EXTRA_FLAGS(obj) & (IS_OBJ_LAZY_UNINITIALIZED | IS_OBJ_LAZY_PROXY)); } -static zend_always_inline bool zend_object_is_lazy_proxy(zend_object *obj) +static zend_always_inline bool zend_object_is_lazy_proxy(const zend_object *obj) { return (OBJ_EXTRA_FLAGS(obj) & IS_OBJ_LAZY_PROXY); } -static zend_always_inline bool zend_lazy_object_initialized(zend_object *obj) +static zend_always_inline bool zend_lazy_object_initialized(const zend_object *obj) { return !(OBJ_EXTRA_FLAGS(obj) & IS_OBJ_LAZY_UNINITIALIZED); } /* True if accessing a lazy prop on obj mandates a call to * zend_lazy_object_init() */ -static zend_always_inline bool zend_lazy_object_must_init(zend_object *obj) +static zend_always_inline bool zend_lazy_object_must_init(const zend_object *obj) { return zend_object_is_lazy(obj); } -static inline bool zend_lazy_object_initialize_on_serialize(zend_object *obj) +static inline bool zend_lazy_object_initialize_on_serialize(const zend_object *obj) { return !(zend_lazy_object_get_flags(obj) & ZEND_LAZY_OBJECT_SKIP_INITIALIZATION_ON_SERIALIZE); } diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c index 8c42b2494ea08..28a275e6fce74 100644 --- a/Zend/zend_llist.c +++ b/Zend/zend_llist.c @@ -121,7 +121,6 @@ ZEND_API void zend_llist_destroy(zend_llist *l) ZEND_API void zend_llist_clean(zend_llist *l) { zend_llist_destroy(l); - l->head = l->tail = NULL; } diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index bdeb435d44319..d3b03ac79a203 100644 --- a/Zend/zend_multiply.h +++ b/Zend/zend_multiply.h @@ -155,13 +155,15 @@ static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, si __asm__ ("mull %3\n\tadcl $0,%1" : "=&a"(res), "=&d" (m_overflow) : "%0"(res), - "rm"(size)); + "rm"(size) + : "cc"); } else { __asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1" : "=&a"(res), "=&d" (m_overflow) : "%0"(res), "rm"(size), - "rm"(offset)); + "rm"(offset) + : "cc"); } if (UNEXPECTED(m_overflow)) { @@ -176,7 +178,7 @@ static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, si static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, size_t offset, bool *overflow) { - size_t res = nmemb; + size_t res; zend_ulong m_overflow = 0; #ifdef __ILP32__ /* x32 */ @@ -186,19 +188,30 @@ static zend_always_inline size_t zend_safe_address(size_t nmemb, size_t size, si #endif if (ZEND_CONST_COND(offset == 0, 0)) { + res = nmemb; __asm__ ("mul" LP_SUFF " %3\n\t" "adc $0,%1" : "=&a"(res), "=&d" (m_overflow) : "%0"(res), - "rm"(size)); + "rm"(size) + : "cc"); + } else if (ZEND_CONST_COND(nmemb == 1, 0)) { + res = size; + __asm__ ("add %2, %0\n\t" + "adc $0,%1" + : "+r"(res), "+r" (m_overflow) + : "rm"(offset) + : "cc"); } else { + res = nmemb; __asm__ ("mul" LP_SUFF " %3\n\t" "add %4,%0\n\t" "adc $0,%1" : "=&a"(res), "=&d" (m_overflow) : "%0"(res), "rm"(size), - "rm"(offset)); + "rm"(offset) + : "cc"); } #undef LP_SUFF if (UNEXPECTED(m_overflow)) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 3d782b03fe174..cca69e5d792c9 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -223,6 +223,8 @@ ZEND_API HashTable *zend_std_get_debug_info(zend_object *object, int *is_temp) / return Z_ARRVAL(retval); } } else if (Z_TYPE(retval) == IS_NULL) { + zend_error(E_DEPRECATED, "Returning null from %s::__debugInfo() is deprecated, return an empty array instead", + ZSTR_VAL(ce->name)); *is_temp = 1; ht = zend_new_array(0); return ht; @@ -285,11 +287,11 @@ static zend_always_inline bool is_derived_class(const zend_class_entry *child_cl static zend_never_inline int is_protected_compatible_scope(const zend_class_entry *ce, const zend_class_entry *scope) /* {{{ */ { return scope && - (is_derived_class(ce, scope) || is_derived_class(scope, ce)); + (ce == scope || is_derived_class(ce, scope) || is_derived_class(scope, ce)); } /* }}} */ -static zend_never_inline zend_property_info *zend_get_parent_private_property(zend_class_entry *scope, const zend_class_entry *ce, zend_string *member) /* {{{ */ +static zend_never_inline zend_property_info *zend_get_parent_private_property(const zend_class_entry *scope, const zend_class_entry *ce, zend_string *member) /* {{{ */ { zval *zv; zend_property_info *prop_info; @@ -350,7 +352,7 @@ static ZEND_COLD zend_never_inline void zend_readonly_property_unset_error( ZSTR_VAL(ce->name), ZSTR_VAL(member)); } -static zend_always_inline zend_class_entry *get_fake_or_executed_scope(void) +static zend_always_inline const zend_class_entry *get_fake_or_executed_scope(void) { if (UNEXPECTED(EG(fake_scope))) { return EG(fake_scope); @@ -391,7 +393,7 @@ static zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *c flags = property_info->flags; if (flags & (ZEND_ACC_CHANGED|ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { - zend_class_entry *scope = get_fake_or_executed_scope(); + const zend_class_entry *scope = get_fake_or_executed_scope(); if (property_info->ce != scope) { if (flags & ZEND_ACC_CHANGED) { @@ -422,7 +424,7 @@ static zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *c } } else { ZEND_ASSERT(flags & ZEND_ACC_PROTECTED); - if (UNEXPECTED(!is_protected_compatible_scope(property_info->ce, scope))) { + if (UNEXPECTED(!is_protected_compatible_scope(property_info->prototype->ce, scope))) { goto wrong; } } @@ -491,7 +493,7 @@ ZEND_API zend_property_info *zend_get_property_info(const zend_class_entry *ce, flags = property_info->flags; if (flags & (ZEND_ACC_CHANGED|ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { - zend_class_entry *scope = get_fake_or_executed_scope(); + const zend_class_entry *scope = get_fake_or_executed_scope(); if (property_info->ce != scope) { if (flags & ZEND_ACC_CHANGED) { zend_property_info *p = zend_get_parent_private_property(scope, ce, member); @@ -517,7 +519,7 @@ ZEND_API zend_property_info *zend_get_property_info(const zend_class_entry *ce, } } else { ZEND_ASSERT(flags & ZEND_ACC_PROTECTED); - if (UNEXPECTED(!is_protected_compatible_scope(property_info->ce, scope))) { + if (UNEXPECTED(!is_protected_compatible_scope(property_info->prototype->ce, scope))) { goto wrong; } } @@ -583,12 +585,12 @@ ZEND_API zend_result zend_check_property_access(const zend_object *zobj, zend_st ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_property_info *prop_info) { ZEND_ASSERT(prop_info->flags & ZEND_ACC_PPP_SET_MASK); ZEND_ASSERT(!(prop_info->flags & ZEND_ACC_PUBLIC_SET)); - zend_class_entry *scope = get_fake_or_executed_scope(); + const zend_class_entry *scope = get_fake_or_executed_scope(); if (prop_info->ce == scope) { return true; } return EXPECTED((prop_info->flags & ZEND_ACC_PROTECTED_SET) - && is_protected_compatible_scope(prop_info->ce, scope)); + && is_protected_compatible_scope(prop_info->prototype->ce, scope)); } static void zend_property_guard_dtor(zval *el) /* {{{ */ { @@ -1823,7 +1825,7 @@ static zend_always_inline zend_function *zend_get_user_call_function(zend_class_ } /* }}} */ -ZEND_API ZEND_COLD zend_never_inline void zend_bad_method_call(zend_function *fbc, zend_string *method_name, zend_class_entry *scope) /* {{{ */ +ZEND_API ZEND_COLD zend_never_inline void zend_bad_method_call(const zend_function *fbc, const zend_string *method_name, const zend_class_entry *scope) /* {{{ */ { zend_throw_error(NULL, "Call to %s method %s::%s() from %s%s", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(method_name), @@ -1833,7 +1835,7 @@ ZEND_API ZEND_COLD zend_never_inline void zend_bad_method_call(zend_function *fb } /* }}} */ -ZEND_API ZEND_COLD zend_never_inline void zend_abstract_method_call(zend_function *fbc) /* {{{ */ +ZEND_API ZEND_COLD zend_never_inline void zend_abstract_method_call(const zend_function *fbc) /* {{{ */ { zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); @@ -1949,17 +1951,15 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st zval *func = zend_hash_find(&ce->function_table, lc_function_name); if (EXPECTED(func)) { fbc = Z_FUNC_P(func); - if (!(fbc->op_array.fn_flags & ZEND_ACC_PUBLIC)) { + if (!(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { zend_class_entry *scope = zend_get_executed_scope(); - if (UNEXPECTED(fbc->common.scope != scope)) { - if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) { - zend_function *fallback_fbc = get_static_method_fallback(ce, function_name); - if (!fallback_fbc) { - zend_bad_method_call(fbc, function_name, scope); - } - fbc = fallback_fbc; + ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(fbc, scope)) { + zend_function *fallback_fbc = get_static_method_fallback(ce, function_name); + if (!fallback_fbc) { + zend_bad_method_call(fbc, function_name, scope); } + fbc = fallback_fbc; } } } else { @@ -2032,10 +2032,10 @@ ZEND_API zval *zend_std_get_static_property_with_info(zend_class_entry *ce, zend } if (!(property_info->flags & ZEND_ACC_PUBLIC)) { - zend_class_entry *scope = get_fake_or_executed_scope(); + const zend_class_entry *scope = get_fake_or_executed_scope(); if (property_info->ce != scope) { if (UNEXPECTED(property_info->flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!is_protected_compatible_scope(property_info->ce, scope))) { + || UNEXPECTED(!is_protected_compatible_scope(property_info->prototype->ce, scope))) { if (type != BP_VAR_IS) { zend_bad_property_access(property_info, ce, property_name); } @@ -2090,14 +2090,14 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p return zend_std_get_static_property_with_info(ce, property_name, type, &prop_info); } -ZEND_API ZEND_COLD bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name) /* {{{ */ +ZEND_API ZEND_COLD bool zend_std_unset_static_property(const zend_class_entry *ce, const zend_string *property_name) /* {{{ */ { zend_throw_error(NULL, "Attempt to unset static property %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(property_name)); return 0; } /* }}} */ -static ZEND_COLD zend_never_inline void zend_bad_constructor_call(zend_function *constructor, zend_class_entry *scope) /* {{{ */ +static ZEND_COLD zend_never_inline void zend_bad_constructor_call(const zend_function *constructor, const zend_class_entry *scope) /* {{{ */ { if (scope) { zend_throw_error(NULL, "Call to %s %s::%s() from scope %s", @@ -2115,15 +2115,13 @@ ZEND_API zend_function *zend_std_get_constructor(zend_object *zobj) /* {{{ */ zend_function *constructor = zobj->ce->constructor; if (constructor) { - if (UNEXPECTED(!(constructor->op_array.fn_flags & ZEND_ACC_PUBLIC))) { - zend_class_entry *scope = get_fake_or_executed_scope(); - if (UNEXPECTED(constructor->common.scope != scope)) { - if (UNEXPECTED(constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), scope))) { - zend_bad_constructor_call(constructor, scope); - zend_object_store_ctor_failed(zobj); - constructor = NULL; - } + if (UNEXPECTED(!(constructor->common.fn_flags & ZEND_ACC_PUBLIC))) { + const zend_class_entry *scope = get_fake_or_executed_scope(); + ZEND_ASSERT(!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(constructor, scope)) { + zend_bad_constructor_call(constructor, scope); + zend_object_store_ctor_failed(zobj); + constructor = NULL; } } } @@ -2208,6 +2206,10 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ } Z_PROTECT_RECURSION_P(o1); + GC_ADDREF(zobj1); + GC_ADDREF(zobj2); + int ret; + for (i = 0; i < zobj1->ce->default_properties_count; i++) { zval *p1, *p2; @@ -2222,31 +2224,45 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */ if (Z_TYPE_P(p1) != IS_UNDEF) { if (Z_TYPE_P(p2) != IS_UNDEF) { - int ret; - ret = zend_compare(p1, p2); if (ret != 0) { Z_UNPROTECT_RECURSION_P(o1); - return ret; + goto done; } } else { Z_UNPROTECT_RECURSION_P(o1); - return 1; + ret = 1; + goto done; } } else { if (Z_TYPE_P(p2) != IS_UNDEF) { Z_UNPROTECT_RECURSION_P(o1); - return 1; + ret = 1; + goto done; } } } Z_UNPROTECT_RECURSION_P(o1); - return 0; + ret = 0; + +done: + OBJ_RELEASE(zobj1); + OBJ_RELEASE(zobj2); + + return ret; } else { - return zend_compare_symbol_tables( + GC_ADDREF(zobj1); + GC_ADDREF(zobj2); + + int ret = zend_compare_symbol_tables( zend_std_get_properties_ex(zobj1), zend_std_get_properties_ex(zobj2)); + + OBJ_RELEASE(zobj1); + OBJ_RELEASE(zobj2); + + return ret; } } /* }}} */ @@ -2545,6 +2561,7 @@ ZEND_API const zend_object_handlers std_object_handlers = { zend_object_std_dtor, /* free_obj */ zend_objects_destroy_object, /* dtor_obj */ zend_objects_clone_obj, /* clone_obj */ + zend_objects_clone_obj_with, /* clone_obj_with */ zend_std_read_property, /* read_property */ zend_std_write_property, /* write_property */ diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 7e7d3df37a6ad..84d0b57d7aa28 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -180,6 +180,7 @@ typedef void (*zend_object_free_obj_t)(zend_object *object); typedef void (*zend_object_dtor_obj_t)(zend_object *object); typedef zend_object* (*zend_object_clone_obj_t)(zend_object *object); +typedef zend_object* (*zend_object_clone_obj_with_t)(zend_object *object, const zend_class_entry *scope, const HashTable *properties); /* Get class name for display in var_dump and other debugging functions. * Must be defined and must return a non-NULL value. */ @@ -209,6 +210,7 @@ struct _zend_object_handlers { zend_object_free_obj_t free_obj; /* required */ zend_object_dtor_obj_t dtor_obj; /* required */ zend_object_clone_obj_t clone_obj; /* optional */ + zend_object_clone_obj_with_t clone_obj_with; /* optional */ zend_object_read_property_t read_property; /* required */ zend_object_write_property_t write_property; /* required */ zend_object_read_dimension_t read_dimension; /* required */ @@ -249,7 +251,7 @@ ZEND_API void zend_class_init_statics(zend_class_entry *ce); ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name_strval, const zval *key); ZEND_API zval *zend_std_get_static_property_with_info(zend_class_entry *ce, zend_string *property_name, int type, struct _zend_property_info **prop_info); ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, int type); -ZEND_API ZEND_COLD bool zend_std_unset_static_property(zend_class_entry *ce, zend_string *property_name); +ZEND_API ZEND_COLD bool zend_std_unset_static_property(const zend_class_entry *ce, const zend_string *property_name); ZEND_API zend_function *zend_std_get_constructor(zend_object *object); ZEND_API struct _zend_property_info *zend_get_property_info(const zend_class_entry *ce, zend_string *member, int silent); ZEND_API HashTable *zend_std_get_properties(zend_object *object); @@ -272,8 +274,8 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2); 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); /* Use zend_std_get_properties_ex() */ ZEND_API HashTable *rebuild_object_properties_internal(zend_object *zobj); -ZEND_API ZEND_COLD zend_never_inline void zend_bad_method_call(zend_function *fbc, zend_string *method_name, zend_class_entry *scope); -ZEND_API ZEND_COLD zend_never_inline void zend_abstract_method_call(zend_function *fbc); +ZEND_API ZEND_COLD zend_never_inline void zend_bad_method_call(const zend_function *fbc, const zend_string *method_name, const zend_class_entry *scope); +ZEND_API ZEND_COLD zend_never_inline void zend_abstract_method_call(const zend_function *fbc); static zend_always_inline HashTable *zend_std_get_properties_ex(zend_object *object) { diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index fd0e97c5f4131..4b4187f423859 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -123,49 +123,25 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) zend_object *old_exception; const zend_op *old_opline_before_exception; - if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { - if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) { - /* Ensure that if we're calling a private function, we're allowed to do so. - */ - if (EG(current_execute_data)) { - zend_class_entry *scope = zend_get_executed_scope(); - - if (object->ce != scope) { - zend_throw_error(NULL, - "Call to private %s::__destruct() from %s%s", - ZSTR_VAL(object->ce->name), - scope ? "scope " : "global scope", - scope ? ZSTR_VAL(scope->name) : "" - ); - return; - } - } else { - zend_error(E_WARNING, - "Call to private %s::__destruct() from global scope during shutdown ignored", - ZSTR_VAL(object->ce->name)); + if (destructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) { + if (EG(current_execute_data)) { + zend_class_entry *scope = zend_get_executed_scope(); + /* Ensure that if we're calling a protected or private function, we're allowed to do so. */ + ZEND_ASSERT(!(destructor->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(destructor, scope)) { + zend_throw_error(NULL, + "Call to %s %s::__destruct() from %s%s", + zend_visibility_string(destructor->common.fn_flags), ZSTR_VAL(object->ce->name), + scope ? "scope " : "global scope", + scope ? ZSTR_VAL(scope->name) : "" + ); return; } } else { - /* Ensure that if we're calling a protected function, we're allowed to do so. - */ - if (EG(current_execute_data)) { - zend_class_entry *scope = zend_get_executed_scope(); - - if (!zend_check_protected(zend_get_function_root_class(destructor), scope)) { - zend_throw_error(NULL, - "Call to protected %s::__destruct() from %s%s", - ZSTR_VAL(object->ce->name), - scope ? "scope " : "global scope", - scope ? ZSTR_VAL(scope->name) : "" - ); - return; - } - } else { - zend_error(E_WARNING, - "Call to protected %s::__destruct() from global scope during shutdown ignored", - ZSTR_VAL(object->ce->name)); - return; - } + zend_error(E_WARNING, + "Call to %s %s::__destruct() from global scope during shutdown ignored", + zend_visibility_string(destructor->common.fn_flags), ZSTR_VAL(object->ce->name)); + return; } } @@ -288,7 +264,6 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, } if (has_clone_method) { - GC_ADDREF(new_object); zend_call_known_instance_method_with_0_params(new_object->ce->clone, new_object, NULL); if (ZEND_CLASS_HAS_READONLY_PROPS(new_object->ce)) { @@ -298,9 +273,53 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, Z_PROP_FLAG_P(prop) &= ~IS_PROP_REINITABLE; } } + } +} + +ZEND_API zend_object *zend_objects_clone_obj_with(zend_object *old_object, const zend_class_entry *scope, const HashTable *properties) +{ + zend_object *new_object = old_object->handlers->clone_obj(old_object); + + if (EXPECTED(!EG(exception))) { + /* Unlock readonly properties once more. */ + if (ZEND_CLASS_HAS_READONLY_PROPS(new_object->ce)) { + for (uint32_t i = 0; i < new_object->ce->default_properties_count; i++) { + zval* prop = OBJ_PROP_NUM(new_object, i); + Z_PROP_FLAG_P(prop) |= IS_PROP_REINITABLE; + } + } - OBJ_RELEASE(new_object); + const zend_class_entry *old_scope = EG(fake_scope); + + EG(fake_scope) = scope; + + ZEND_HASH_FOREACH_KEY_VAL(properties, zend_ulong num_key, zend_string *key, zval *val) { + if (UNEXPECTED(Z_ISREF_P(val))) { + if (Z_REFCOUNT_P(val) == 1) { + val = Z_REFVAL_P(val); + } else { + zend_throw_error(NULL, "Cannot assign by reference when cloning with updated properties"); + break; + } + } + + if (UNEXPECTED(key == NULL)) { + key = zend_long_to_str(num_key); + new_object->handlers->write_property(new_object, key, val, NULL); + zend_string_release_ex(key, false); + } else { + new_object->handlers->write_property(new_object, key, val, NULL); + } + + if (UNEXPECTED(EG(exception))) { + break; + } + } ZEND_HASH_FOREACH_END(); + + EG(fake_scope) = old_scope; } + + return new_object; } ZEND_API zend_object *zend_objects_clone_obj(zend_object *old_object) diff --git a/Zend/zend_objects.h b/Zend/zend_objects.h index 41e3bcd9594b1..712fd442da5a4 100644 --- a/Zend/zend_objects.h +++ b/Zend/zend_objects.h @@ -30,6 +30,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, ZEND_API void zend_object_std_dtor(zend_object *object); ZEND_API void zend_objects_destroy_object(zend_object *object); ZEND_API zend_object *zend_objects_clone_obj(zend_object *object); +ZEND_API zend_object *zend_objects_clone_obj_with(zend_object *object, const zend_class_entry *scope, const HashTable *properties); void zend_object_dtor_dynamic_properties(zend_object *object); void zend_object_dtor_property(zend_object *object, zval *p); diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index 242bf212ba9c6..86c3a49f8c8c5 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -137,5 +137,16 @@ static inline zend_property_info *zend_get_typed_property_info_for_slot(zend_obj return NULL; } +static zend_always_inline bool zend_check_method_accessible(const zend_function *fn, const zend_class_entry *scope) +{ + if (!(fn->common.fn_flags & ZEND_ACC_PUBLIC) + && fn->common.scope != scope + && (UNEXPECTED(fn->common.fn_flags & ZEND_ACC_PRIVATE) + || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fn), scope)))) { + return false; + } + + return true; +} #endif /* ZEND_OBJECTS_H */ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 6e7d31e15a40f..f3631104c62c3 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -709,7 +709,7 @@ static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num } } -static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) { +static uint32_t zend_get_brk_cont_target(const zend_op *opline) { int nest_levels = opline->op2.num; int array_offset = opline->op1.num; zend_brk_cont_element *jmp_to; @@ -903,7 +903,8 @@ static bool keeps_op1_alive(zend_op *opline) { || opline->opcode == ZEND_MATCH_ERROR || opline->opcode == ZEND_FETCH_LIST_R || opline->opcode == ZEND_FETCH_LIST_W - || opline->opcode == ZEND_COPY_TMP) { + || opline->opcode == ZEND_COPY_TMP + || opline->opcode == ZEND_EXT_STMT) { return 1; } ZEND_ASSERT(opline->opcode != ZEND_FE_FETCH_R @@ -1120,7 +1121,7 @@ ZEND_API void pass_two(zend_op_array *op_array) case ZEND_BRK: case ZEND_CONT: { - uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline); + uint32_t jmp_target = zend_get_brk_cont_target(opline); if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) { zend_check_finally_breakout(op_array, opline - op_array->opcodes, jmp_target); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 712a6039dfb14..e6e0c82c79f20 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -402,6 +402,7 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * zend_long lval; double dval; bool trailing_data = false; + zend_string *op_str = NULL; /* protect against error handlers */ /* For BC reasons we allow errors so that we can warn on leading numeric string */ type = is_numeric_string_ex(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval, @@ -411,6 +412,9 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * return 0; } if (UNEXPECTED(trailing_data)) { + if (type != IS_LONG) { + op_str = zend_string_copy(Z_STR_P(op)); + } zend_error(E_WARNING, "A non-numeric value encountered"); if (UNEXPECTED(EG(exception))) { *failed = 1; @@ -426,11 +430,12 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * */ lval = zend_dval_to_lval_cap(dval); if (!zend_is_long_compatible(dval, lval)) { - zend_incompatible_string_to_long_error(Z_STR_P(op)); + zend_incompatible_string_to_long_error(op_str ? op_str : Z_STR_P(op)); if (UNEXPECTED(EG(exception))) { *failed = 1; } } + zend_tmp_string_release(op_str); return lval; } } @@ -2553,29 +2558,23 @@ static bool ZEND_FASTCALL increment_string(zval *str) /* {{{ */ int last=0; /* Shut up the compiler warning */ int ch; + zend_string *zstr = Z_STR_P(str); + zend_string_addref(zstr); + zend_error(E_DEPRECATED, "Increment on non-numeric string is deprecated, use str_increment() instead"); + if (EG(exception)) { + zend_string_release(zstr); + return false; + } + /* A userland error handler can change the type from string to something else */ + zval_ptr_dtor(str); + ZVAL_STR(str, zstr); + if (UNEXPECTED(Z_STRLEN_P(str) == 0)) { - zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); - if (EG(exception)) { - return false; - } - /* A userland error handler can change the type from string to something else */ zval_ptr_dtor(str); ZVAL_CHAR(str, '1'); return true; } - if (UNEXPECTED(!zend_string_only_has_ascii_alphanumeric(Z_STR_P(str)))) { - zend_string *zstr = Z_STR_P(str); - zend_string_addref(zstr); - zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); - if (EG(exception)) { - zend_string_release(zstr); - return false; - } - zval_ptr_dtor(str); - ZVAL_STR(str, zstr); - } - if (!Z_REFCOUNTED_P(str)) { Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0); Z_TYPE_INFO_P(str) = IS_STRING_EX; @@ -3417,7 +3416,19 @@ static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */ ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2) /* {{{ */ { - return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0); + if (ht1 == ht2) { + return 0; + } + + GC_TRY_ADDREF(ht1); + GC_TRY_ADDREF(ht2); + + int ret = zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0); + + GC_TRY_DTOR_NO_REF(ht1); + GC_TRY_DTOR_NO_REF(ht2); + + return ret; } /* }}} */ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index a7537d1b3ef33..63b0fb62e49f2 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -215,7 +215,7 @@ zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const static zend_always_inline const void *zend_memrchr(const void *s, int c, size_t n) { -#if defined(HAVE_MEMRCHR) && !defined(i386) +#if defined(HAVE_MEMRCHR) && !defined(__i386__) /* On x86 memrchr() doesn't use SSE/AVX, so inlined version is faster */ return (const void*)memrchr(s, c, n); #else diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 97bd038ecf3d8..c7e12d58c1f53 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -89,6 +89,9 @@ #ifndef __has_feature # define __has_feature(x) 0 #endif +#ifndef __has_include +# define __has_include(x) 0 +#endif #if defined(ZEND_WIN32) && !defined(__clang__) # define ZEND_ASSUME(c) __assume(c) @@ -109,7 +112,10 @@ # define ZEND_ASSERT(c) ZEND_ASSUME(c) #endif -#ifdef PHP_HAVE_BUILTIN_UNREACHABLE +/* use C23 unreachable() from if possible */ +#ifdef unreachable +# define _ZEND_UNREACHABLE() unreachable() +#elif defined(PHP_HAVE_BUILTIN_UNREACHABLE) # define _ZEND_UNREACHABLE() __builtin_unreachable() #else # define _ZEND_UNREACHABLE() ZEND_ASSUME(0) @@ -245,6 +251,14 @@ char *alloca(); # define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y) #endif +#if __STDC_VERSION__ >= 202311L || (defined(__cplusplus) && __cplusplus >= 201703L) +# define ZEND_ATTRIBUTE_NODISCARD [[nodiscard]] +#elif __has_attribute(__warn_unused_result__) +# define ZEND_ATTRIBUTE_NODISCARD __attribute__((__warn_unused_result__)) +#else +# define ZEND_ATTRIBUTE_NODISCARD +#endif + #if ZEND_GCC_VERSION >= 3000 # define ZEND_ATTRIBUTE_CONST __attribute__((const)) #else @@ -318,6 +332,15 @@ char *alloca(); # define ZEND_FASTCALL #endif +#ifdef HAVE_PRESERVE_NONE +# define ZEND_PRESERVE_NONE __attribute__((preserve_none)) +#endif + +#if __has_attribute(musttail) +# define HAVE_MUSTTAIL +# define ZEND_MUSTTAIL __attribute__((musttail)) +#endif + #if (defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(__APPLE__) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__)) || __has_attribute(noreturn) # define HAVE_NORETURN # define ZEND_NORETURN __attribute__((noreturn)) @@ -496,6 +519,8 @@ extern "C++" { #ifdef ZEND_WIN32 #define ZEND_SECURE_ZERO(var, size) RtlSecureZeroMemory((var), (size)) +#elif defined(HAVE_MEMSET_EXPLICIT) +#define ZEND_SECURE_ZERO(var, size) memset_explicit((var), 0, (size)) #else #define ZEND_SECURE_ZERO(var, size) explicit_bzero((var), (size)) #endif @@ -728,6 +753,10 @@ extern "C++" { # define ZEND_SET_ALIGNED(alignment, decl) decl #endif +#if __has_attribute(section) +# define HAVE_ATTRIBUTE_SECTION +#endif + #define ZEND_SLIDE_TO_ALIGNED(alignment, ptr) (((uintptr_t)(ptr) + ((alignment)-1)) & ~((alignment)-1)) #define ZEND_SLIDE_TO_ALIGNED16(ptr) ZEND_SLIDE_TO_ALIGNED(Z_UL(16), ptr) @@ -764,7 +793,7 @@ extern "C++" { # define ZEND_INDIRECT_RETURN #endif -#if __has_attribute(nonstring) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 15 +#if __has_attribute(nonstring) && defined(__GNUC__) && ((!defined(__clang__) && __GNUC__ >= 15) || (defined(__clang_major__) && __clang_major__ >= 20)) # define ZEND_NONSTRING __attribute__((nonstring)) #else # define ZEND_NONSTRING @@ -794,7 +823,9 @@ extern "C++" { /** @deprecated */ #define ZEND_CGG_DIAGNOSTIC_IGNORED_END ZEND_DIAGNOSTIC_IGNORED_END -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ +#if defined(__cplusplus) +# define ZEND_STATIC_ASSERT(c, m) static_assert((c), m) +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ # define ZEND_STATIC_ASSERT(c, m) _Static_assert((c), m) #else # define ZEND_STATIC_ASSERT(c, m) diff --git a/Zend/zend_string.h b/Zend/zend_string.h index f60e4dec4e71f..87f221125202c 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -70,15 +70,6 @@ END_EXTERN_C() #define ZSTR_H(zstr) (zstr)->h #define ZSTR_HASH(zstr) zend_string_hash_val(zstr) -/* Compatibility macros */ - -#define IS_INTERNED(s) ZSTR_IS_INTERNED(s) -#define STR_EMPTY_ALLOC() ZSTR_EMPTY_ALLOC() -#define _STR_HEADER_SIZE _ZSTR_HEADER_SIZE -#define STR_ALLOCA_ALLOC(str, _len, use_heap) ZSTR_ALLOCA_ALLOC(str, _len, use_heap) -#define STR_ALLOCA_INIT(str, s, len, use_heap) ZSTR_ALLOCA_INIT(str, s, len, use_heap) -#define STR_ALLOCA_FREE(str, use_heap) ZSTR_ALLOCA_FREE(str, use_heap) - /*---*/ #define ZSTR_IS_INTERNED(s) (GC_FLAGS(s) & IS_STR_INTERNED) @@ -645,6 +636,12 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_SINCE, "since") \ _(ZEND_STR_GET, "get") \ _(ZEND_STR_SET, "set") \ + _(ZEND_STR_8_DOT_0, "8.0") \ + _(ZEND_STR_8_DOT_1, "8.1") \ + _(ZEND_STR_8_DOT_2, "8.2") \ + _(ZEND_STR_8_DOT_3, "8.3") \ + _(ZEND_STR_8_DOT_4, "8.4") \ + _(ZEND_STR_8_DOT_5, "8.5") \ typedef enum _zend_known_string_id { diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 4a6d00b9d73ea..a3d3e4da6362d 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -753,6 +753,18 @@ static zend_always_inline uint8_t zval_get_type(const zval* pz) { } \ } while (0) +#define GC_TRY_DTOR_NO_REF(p) \ + do { \ + zend_refcounted_h *_p = &(p)->gc; \ + if (!(_p->u.type_info & GC_IMMUTABLE)) { \ + if (zend_gc_delref(_p) == 0) { \ + rc_dtor_func((zend_refcounted *)_p); \ + } else { \ + gc_check_possible_root_no_ref((zend_refcounted *)_p); \ + } \ + } \ + } while (0) + #define GC_TYPE_MASK 0x0000000f #define GC_FLAGS_MASK 0x000003f0 #define GC_INFO_MASK 0xfffffc00 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index be7bc8b37b7dd..3d6463d064873 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2962,7 +2962,10 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) { zend_execute_data *old_execute_data; uint32_t call_info = EX_CALL_INFO(); +#if ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL + /* zend_leave_helper may be called with opline=call_leave_op in TAILCALL VM */ SAVE_OPLINE(); +#endif if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); @@ -4917,7 +4920,7 @@ ZEND_VM_HOT_SEND_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, CONST|UNUSED|NUM, SPE ZEND_VM_C_GOTO(send_val_by_ref); } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -ZEND_VM_C_LABEL(send_val_by_ref): +ZEND_VM_C_LABEL(send_val_by_ref):; ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper, _arg_num, arg_num, _arg, arg); } value = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -5392,6 +5395,11 @@ ZEND_VM_C_LABEL(send_again): } name = Z_STR_P(&key); + + zend_ulong tmp; + if (ZEND_HANDLE_NUMERIC(name, tmp)) { + name = NULL; + } } } @@ -6006,7 +6014,8 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) SAVE_OPLINE(); obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); - /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. */ + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ do { if (OP1_TYPE == IS_CONST || @@ -6043,14 +6052,12 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { scope = EX(func)->op_array.scope; - if (clone->common.scope != scope) { - if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_wrong_clone_call(clone, scope); - FREE_OP1(); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + FREE_OP1(); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -6158,7 +6165,7 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO } bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; - if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { if (c->ce->type == ZEND_USER_CLASS) { /* Recursion protection only applied to user constants, GH-18463 */ CONST_PROTECT_RECURSION(c); @@ -6321,17 +6328,22 @@ ZEND_VM_C_LABEL(add_unpack_again): zval *val; if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { - zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); - ZEND_HASH_FILL_PACKED(result_ht) { - ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { - if (UNEXPECTED(Z_ISREF_P(val)) && - UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { - val = Z_REFVAL_P(val); - } - Z_TRY_ADDREF_P(val); - ZEND_HASH_FILL_ADD(val); - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FILL_END(); + /* zend_hash_extend() skips initialization when the number of elements is 0, + * but the code below expects that result_ht is initialized as packed. + * We can just skip the work in that case. */ + if (result_ht->nNumUsed + zend_hash_num_elements(ht) > 0) { + zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); + ZEND_HASH_FILL_PACKED(result_ht) { + ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { + if (UNEXPECTED(Z_ISREF_P(val)) && + UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { + val = Z_REFVAL_P(val); + } + Z_TRY_ADDREF_P(val); + ZEND_HASH_FILL_ADD(val); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } } else { zend_string *key; @@ -7934,7 +7946,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST) if (zv) { SAVE_OPLINE(); ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2))); - if (!ce) { + if (EG(exception)) { HANDLE_EXCEPTION(); } } @@ -7958,7 +7970,7 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT) if (!(ce->ce_flags & ZEND_ACC_LINKED)) { SAVE_OPLINE(); ce = zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL, rtd_key); - if (!ce) { + if (EG(exception)) { HANDLE_EXCEPTION(); } } @@ -8261,7 +8273,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); c.name = zend_string_copy(Z_STR_P(name)); - if (zend_register_constant(&c) == FAILURE) { + if (zend_register_constant(&c) == NULL) { } FREE_OP1(); @@ -8274,7 +8286,7 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST) USE_OPLINE zval *name; zval *val; - zend_constant c; + zend_constant c, *registered; SAVE_OPLINE(); name = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -8293,7 +8305,8 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST) ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); c.name = zend_string_copy(Z_STR_P(name)); - if (zend_register_constant(&c) == FAILURE) { + registered = zend_register_constant(&c); + if (registered == NULL) { FREE_OP1(); FREE_OP2(); /* two opcodes used, second one is the data with attributes */ @@ -8301,9 +8314,7 @@ ZEND_VM_HANDLER(210, ZEND_DECLARE_ATTRIBUTED_CONST, CONST, CONST) } HashTable *attributes = Z_PTR_P(GET_OP_DATA_ZVAL_PTR(BP_VAR_R)); - zend_constant *registered = zend_get_constant_ptr(c.name); ZEND_ASSERT(attributes != NULL); - ZEND_ASSERT(registered != NULL); zend_constant_add_attributes(registered, attributes); FREE_OP1(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 3a13f4244d361..92e5f327fd08a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -321,18 +321,22 @@ static uint8_t zend_user_opcodes[256] = {0, #define SPEC_RULE_OBSERVER 0x02000000 static const uint32_t *zend_spec_handlers; -static const void * const *zend_opcode_handlers; +static zend_vm_opcode_handler_t const *zend_opcode_handlers; static int zend_handlers_count; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) -static const void * const * zend_opcode_handler_funcs; +static zend_vm_opcode_handler_func_t const * zend_opcode_handler_funcs; static zend_op hybrid_halt_op; #endif -#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC -static const void *zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op); +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + +static zend_vm_opcode_handler_func_t const * zend_opcode_handler_funcs; +#endif +#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) || !ZEND_VM_SPEC +static zend_vm_opcode_handler_t zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op); #endif -#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) -static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op); +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +static zend_vm_opcode_handler_func_t zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op); #else # define zend_vm_get_opcode_handler_func zend_vm_get_opcode_handler #endif @@ -381,11 +385,7 @@ static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) # define ZEND_OPCODE_HANDLER_RET void # define ZEND_VM_TAIL_CALL(call) call; return -# ifdef ZEND_VM_TAIL_CALL_DISPATCH -# define ZEND_VM_CONTINUE() ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); return -# else -# define ZEND_VM_CONTINUE() return -# endif +# define ZEND_VM_CONTINUE() return # if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) # define ZEND_VM_RETURN() opline = &hybrid_halt_op; return # define ZEND_VM_HOT zend_always_inline ZEND_COLD ZEND_OPT_SIZE @@ -403,8 +403,7 @@ static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op # define ZEND_VM_HOT # define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE #endif - -typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); +#define ZEND_VM_DISPATCH_TO_HELPER(call) ZEND_VM_TAIL_CALL(call) #ifdef ZEND_VM_IP_GLOBAL_REG # define DCL_OPLINE @@ -443,12 +442,12 @@ typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_H #endif #define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); #define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler_func(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler_func(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS); -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -469,7 +468,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_add_helper_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -490,7 +489,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_sub_helper_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -511,7 +510,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mul_helper_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mod_by_zero_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_mod_by_zero_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -521,7 +520,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mo HANDLE_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -542,7 +541,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mod_helper_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -563,7 +562,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_left_h ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -584,7 +583,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -606,7 +605,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_hel ZEND_VM_SMART_BRANCH(ret == 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -628,7 +627,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal ZEND_VM_SMART_BRANCH(ret != 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -650,7 +649,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_h ZEND_VM_SMART_BRANCH(ret < 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -672,7 +671,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_o ZEND_VM_SMART_BRANCH(ret <= 0, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -693,7 +692,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_or_helper ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -714,7 +713,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_and_helpe ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { USE_OPLINE @@ -735,7 +734,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_xor_helpe ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) { USE_OPLINE @@ -748,7 +747,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_bw_not_helpe ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_this_not_in_object_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -758,7 +757,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_th HANDLE_EXCEPTION(); } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_undefined_function_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_undefined_function_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -769,7 +768,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_un HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { /* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */ @@ -824,7 +823,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_OP_SPEC_HAN ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *prop; @@ -852,7 +851,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_STATIC_PROP_SPEC_HANDL } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *prop; @@ -915,25 +914,25 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_ } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_STATIC_PROP_R_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_STATIC_PROP_W_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_STATIC_PROP_RW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { ZEND_VM_TAIL_CALL(ZEND_FETCH_STATIC_PROP_W_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -943,18 +942,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPE } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_STATIC_PROP_UNSET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_STATIC_PROP_IS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_use_tmp_in_write_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -966,7 +965,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_us HANDLE_EXCEPTION(); } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_use_undef_in_read_context_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -978,7 +977,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_us HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *prop, *value; @@ -990,6 +989,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { + UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -999,6 +999,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT if (ZEND_TYPE_IS_SET(prop_info->type)) { value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); + } else { value = zend_assign_to_variable_ex(prop, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); } @@ -1015,7 +1016,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *prop, *value; @@ -1052,7 +1053,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *prop, *value; @@ -1089,7 +1090,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *prop, *value; @@ -1101,6 +1102,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { + UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -1110,6 +1112,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT if (ZEND_TYPE_IS_SET(prop_info->type)) { value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); + } else { value = zend_assign_to_variable_ex(prop, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); } @@ -1126,7 +1129,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *prop, *value_ptr; @@ -1174,11 +1177,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { zend_execute_data *old_execute_data; uint32_t call_info = EX_CALL_INFO(); +#if ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL + /* zend_leave_helper may be called with opline=call_leave_op in TAILCALL VM */ SAVE_OPLINE(); +#endif if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); @@ -1313,14 +1319,14 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1341,6 +1347,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + fbc->internal_function.handler(call, ret); #if ZEND_DEBUG @@ -1356,6 +1363,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV } #endif + ZEND_VM_FCALL_INTERRUPT_CHECK(call); EG(current_execute_data) = execute_data; @@ -1384,7 +1392,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV ZEND_VM_CONTINUE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1405,6 +1413,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + fbc->internal_function.handler(call, ret); #if ZEND_DEBUG @@ -1420,6 +1429,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV } #endif + ZEND_VM_FCALL_INTERRUPT_CHECK(call); EG(current_execute_data) = execute_data; @@ -1448,7 +1458,7 @@ 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) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_ICALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1513,7 +1523,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_OBS ZEND_VM_CONTINUE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1534,10 +1544,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1558,10 +1570,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETV LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_UCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1586,7 +1600,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_OBS ZEND_VM_ENTER_EX(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1628,6 +1642,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); @@ -1645,6 +1661,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + fbc->internal_function.handler(call, ret); #if ZEND_DEBUG @@ -1660,6 +1677,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S } #endif + ZEND_VM_FCALL_INTERRUPT_CHECK(call); EG(current_execute_data) = execute_data; @@ -1695,7 +1713,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S ZEND_VM_CONTINUE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1737,6 +1755,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); @@ -1754,6 +1774,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + fbc->internal_function.handler(call, ret); #if ZEND_DEBUG @@ -1769,6 +1790,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S } #endif + ZEND_VM_FCALL_INTERRUPT_CHECK(call); EG(current_execute_data) = execute_data; @@ -1804,7 +1826,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S ZEND_VM_CONTINUE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1915,7 +1937,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_ ZEND_VM_CONTINUE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -1962,10 +1984,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { SAVE_OPLINE_EX(); + execute_data = EX(prev_execute_data); LOAD_OPLINE(); ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -1987,6 +2012,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call, ret); @@ -2007,6 +2033,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV } #endif + ZEND_VM_FCALL_INTERRUPT_CHECK(call); EG(current_execute_data) = execute_data; @@ -2040,7 +2067,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_VM_CONTINUE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -2087,10 +2114,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { SAVE_OPLINE_EX(); + execute_data = EX(prev_execute_data); LOAD_OPLINE(); ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -2112,6 +2142,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); + if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(call, ret); @@ -2132,6 +2163,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV } #endif + ZEND_VM_FCALL_INTERRUPT_CHECK(call); EG(current_execute_data) = execute_data; @@ -2165,7 +2197,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV ZEND_VM_CONTINUE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -2291,7 +2323,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBS ZEND_VM_CONTINUE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_CREATE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *return_value = EX(return_value); @@ -2369,7 +2401,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_CREATE_SPEC_HANDLER( } } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t _arg_num, zval *_arg) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t _arg_num, zval *_arg) { USE_OPLINE @@ -2381,7 +2413,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_ca HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *args; @@ -2518,6 +2550,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_ } name = Z_STR_P(&key); + + zend_ulong tmp; + if (ZEND_HANDLE_NUMERIC(name, tmp)) { + name = NULL; + } } } @@ -2594,7 +2631,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *args; @@ -2745,7 +2782,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_missing_arg_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_missing_arg_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -2755,7 +2792,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_mi HANDLE_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_verify_recv_arg_type_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_verify_recv_arg_type_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) { USE_OPLINE @@ -2767,7 +2804,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_verify_recv_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_NOTYPE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RECV_NOTYPE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -2779,7 +2816,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_NOTYPE_SPEC_H ZEND_VM_NEXT_OPCODE(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) { int ret; USE_OPLINE @@ -2798,7 +2835,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_ ZEND_VM_SMART_BRANCH(ret == 0, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -2814,17 +2851,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER( zval *val; if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { - zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); - ZEND_HASH_FILL_PACKED(result_ht) { - ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { - if (UNEXPECTED(Z_ISREF_P(val)) && - UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { - val = Z_REFVAL_P(val); - } - Z_TRY_ADDREF_P(val); - ZEND_HASH_FILL_ADD(val); - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FILL_END(); + /* zend_hash_extend() skips initialization when the number of elements is 0, + * but the code below expects that result_ht is initialized as packed. + * We can just skip the work in that case. */ + if (result_ht->nNumUsed + zend_hash_num_elements(ht) > 0) { + zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); + ZEND_HASH_FILL_PACKED(result_ht) { + ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { + if (UNEXPECTED(Z_ISREF_P(val)) && + UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { + val = Z_REFVAL_P(val); + } + Z_TRY_ADDREF_P(val); + ZEND_HASH_FILL_ADD(val); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } } else { zend_string *key; @@ -2932,7 +2974,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_UNPACK_SPEC_HANDLER( ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varname; @@ -2984,7 +3026,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fe_fetch_object_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_fe_fetch_object_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array; @@ -3102,7 +3144,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fe_fetch_obj ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -3122,7 +3164,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3156,7 +3198,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3168,7 +3210,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_STMT_SPEC_HAN ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3180,7 +3222,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_FCALL_BEGIN_S ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3192,7 +3234,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_FCALL_END_SPE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *zv; zend_class_entry *ce; @@ -3207,7 +3249,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE if (!(ce->ce_flags & ZEND_ACC_LINKED)) { SAVE_OPLINE(); ce = zend_do_link_class(ce, (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL, rtd_key); - if (!ce) { + if (EG(exception)) { HANDLE_EXCEPTION(); } } @@ -3217,7 +3259,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_function *func; USE_OPLINE @@ -3228,7 +3270,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_FUNCTION_SPEC_HANDLER( ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TICKS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_TICKS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3245,21 +3287,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TICKS_SPEC_HANDLER(ZEND_OPCODE ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_EXT_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE ZEND_VM_NEXT_OPCODE(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t try_catch_offset, uint32_t op_num) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t try_catch_offset, uint32_t op_num) { /* May be NULL during generator closing (only finally blocks are executed) */ zend_object *ex = EG(exception); @@ -3336,13 +3378,13 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_dispatch_try } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { const zend_op *throw_op = EG(opline_before_exception); /* Exception was thrown before executing any op */ if (UNEXPECTED(!throw_op)) { - ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); } uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; @@ -3406,10 +3448,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( } } - ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, throw_op_num)); + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, throw_op_num)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE int ret; @@ -3441,7 +3483,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_ } } -static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3453,7 +3495,7 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_yi HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *fast_call = EX_VAR(opline->op1.var); @@ -3477,7 +3519,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *fast_call = EX_VAR(opline->result.var); @@ -3488,7 +3530,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OP ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *fast_call = EX_VAR(opline->op1.var); @@ -3505,10 +3547,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC Z_OBJ_P(fast_call) = NULL; current_try_catch_offset = opline->op2.num; current_op_num = opline - EX(func)->op_array.opcodes; - ZEND_VM_TAIL_CALL(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, current_op_num)); + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, current_op_num)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3523,7 +3565,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_array *args = NULL; zend_function *fbc = EX(func); @@ -3585,10 +3627,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } else { SAVE_OPLINE_EX(); + execute_data = EX(prev_execute_data); if (execute_data) { LOAD_OPLINE(); @@ -3613,6 +3658,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); @@ -3633,6 +3679,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z } #endif + EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3666,7 +3713,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z ZEND_VM_LEAVE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_array *args = NULL; zend_function *fbc = EX(func); @@ -3810,7 +3857,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ ZEND_VM_LEAVE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_2_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_2_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -3844,7 +3891,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_2_SPEC_HANDLER ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_2_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_2_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -3878,7 +3925,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_2_SPEC_OBSERVE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_3_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_3_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -3918,7 +3965,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_3_SPEC_HANDLER ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -3958,7 +4005,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVE ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_FORWARD_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_FORWARD_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3966,7 +4013,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_FORWARD_SPEC_H ZEND_VM_CONTINUE(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { zend_atomic_bool_store_ex(&EG(vm_interrupt), false); SAVE_OPLINE(); @@ -3992,7 +4039,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_he } ZEND_VM_CONTINUE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_function *fbc; @@ -4020,7 +4067,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -4053,6 +4100,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_H if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { + if (UNEXPECTED(EG(exception))) { if (call) { if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { @@ -4073,7 +4121,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *func_name; @@ -4106,7 +4154,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_N ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *fname; @@ -4135,7 +4183,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CO ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_OFFSET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_FCALL_OFFSET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_function *fbc; @@ -4153,7 +4201,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_FCALL_OFFSET_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE uint32_t arg_num; @@ -4203,7 +4251,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -4256,7 +4304,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RECV_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -4269,13 +4317,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H param = EX_VAR(opline->result.var); if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) { - ZEND_VM_TAIL_CALL(zend_verify_recv_arg_type_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX param)); + ZEND_VM_DISPATCH_TO_HELPER(zend_verify_recv_arg_type_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX param)); } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RECV_VARIADIC_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE uint32_t arg_num = opline->op1.num; @@ -4347,7 +4395,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -4373,7 +4421,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_1_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_1_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -4399,7 +4447,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_1_SPEC_OBSERVE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -4432,6 +4480,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HAND if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (UNEXPECTED(EG(exception))) { if (call) { if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { @@ -4452,7 +4501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HAND ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -4463,10 +4512,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -4487,12 +4536,13 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CON SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *z; @@ -4517,10 +4567,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_O zend_string_release_ex(str, 0); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -4554,7 +4605,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_H ZEND_VM_JMP(opline); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -4588,7 +4639,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_ ZEND_VM_JMP(opline); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -4614,6 +4665,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONS SAVE_OPLINE(); ret = i_zend_is_true(val); + if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; @@ -4624,7 +4676,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONS ZEND_VM_JMP(opline); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -4649,6 +4701,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CON SAVE_OPLINE(); ret = i_zend_is_true(val); + if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline = OP_JMP_ADDR(opline, opline->op2); @@ -4659,15 +4712,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CON ZEND_VM_JMP(opline); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -4733,10 +4788,13 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_ + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; @@ -4814,16 +4872,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + SAVE_OPLINE(); return_value = EX(return_value); + do { if ((IS_CONST & (IS_CONST|IS_TMP_VAR)) || (IS_CONST == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -4833,6 +4893,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE retval_ptr = RT_CONSTANT(opline, opline->op1); if (!return_value) { + } else { if (IS_CONST == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -4857,6 +4918,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZVAL_NEW_REF(return_value, retval_ptr); } else { + } break; } @@ -4871,13 +4933,16 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } + } while (0); + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_BY_REF_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; @@ -4943,7 +5008,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval; @@ -4979,6 +5044,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HA } } + EG(current_execute_data) = EX(prev_execute_data); /* Close the generator to free up resources */ @@ -4988,7 +5054,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HA ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RETURN_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval; @@ -5035,7 +5101,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_OBSERVER ZEND_VM_RETURN(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -5059,6 +5125,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_ } zend_throw_error(NULL, "Can only throw objects"); + HANDLE_EXCEPTION(); } } while (0); @@ -5068,10 +5135,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_ zend_throw_exception_object(value); zend_exception_restore(); + HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_class_entry *ce, *catch_ce; @@ -5122,7 +5190,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_USER_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; @@ -5139,10 +5207,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CONST_HANDLER(Z ZVAL_COPY(param, arg); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -5163,12 +5232,13 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_H SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *obj; @@ -5180,7 +5250,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ SAVE_OPLINE(); obj = RT_CONSTANT(opline, opline->op1); - /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. */ + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ do { if (IS_CONST == IS_CONST || @@ -5200,6 +5271,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ } zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj)); + HANDLE_EXCEPTION(); } } while (0); @@ -5211,29 +5283,30 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_ if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { scope = EX(func)->op_array.scope; - if (clone->common.scope != scope) { - if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_wrong_clone_call(clone, scope); + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -5266,6 +5339,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -5277,10 +5351,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_op_array *new_op_array; @@ -5291,6 +5366,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); if (UNEXPECTED(EG(exception) != NULL)) { + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { destroy_op_array(new_op_array); efree_size(new_op_array, sizeof(zend_op_array)); @@ -5340,8 +5416,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); + if (EXPECTED(zend_execute_ex == execute_ex)) { + ZEND_VM_ENTER(); } else { ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -5355,15 +5433,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); + UNDEF_RESULT(); HANDLE_EXCEPTION(); } } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_op_array *new_op_array; @@ -5446,7 +5526,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_R_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *result; @@ -5462,6 +5542,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( } Z_FE_POS_P(result) = 0; + ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { zend_object *zobj = Z_OBJ_P(array_ptr); @@ -5471,6 +5552,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -5495,15 +5577,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(result) = (uint32_t) -1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -5517,11 +5602,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CONST_HANDLER( ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_RW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *array_ref; @@ -5557,6 +5643,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { if (!Z_OBJCE_P(array_ptr)->get_iterator) { @@ -5567,6 +5654,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -5593,15 +5681,18 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -5615,11 +5706,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_ ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -5640,6 +5732,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONS if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -5662,10 +5755,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONS ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COALESCE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -5706,7 +5800,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CON ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_NULL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val, *result; @@ -5719,6 +5813,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_CON val = Z_REFVAL_P(val); if (Z_TYPE_P(val) <= IS_NULL) { + break; } } @@ -5750,7 +5845,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_CON ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -5788,7 +5883,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CON ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5797,7 +5892,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDL ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_function *func; @@ -5824,7 +5919,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); @@ -5836,6 +5931,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -5848,6 +5944,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( } Z_FE_POS(generator->values) = 0; + } else if (IS_CONST != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { zend_class_entry *ce = Z_OBJCE_P(val); if (ce == zend_ce_generator) { @@ -5855,6 +5952,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( Z_ADDREF_P(val); + if (UNEXPECTED(new_gen->execute_data == NULL)) { zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); zval_ptr_dtor(val); @@ -5878,6 +5976,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( } else { zend_object_iterator *iter = ce->get_iterator(ce, val, 0); + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { if (!EG(exception)) { zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); @@ -5904,6 +6003,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( } else { zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -5924,7 +6024,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( ZEND_VM_RETURN(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -5944,6 +6044,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + ZEND_VM_NEXT_OPCODE(); } } @@ -5983,10 +6084,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST } while (0); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -6016,13 +6118,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_C if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); + ZEND_VM_SMART_BRANCH(result, 1); } else { ZEND_VM_SMART_BRANCH(result, 0); } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DEFINED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_constant *c; @@ -6045,7 +6148,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_FRAMELESS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_jmp_fl_result result = (uintptr_t)CACHED_PTR(opline->extended_value); @@ -6068,7 +6171,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_FRAMELESS_SPEC_CONST_HANDL } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_LONG_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -6078,7 +6181,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPE ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -6088,7 +6191,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_S ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_NOREF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -6098,7 +6201,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SP ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -6109,7 +6212,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SIMPLE_SP ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -6117,14 +6220,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SIMPLE arg = ZEND_CALL_VAR(EX(call), opline->result.var); if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -6159,10 +6262,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -6197,10 +6300,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -6238,10 +6341,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6252,10 +6355,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CO div_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MOD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -6279,10 +6384,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CO } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6300,10 +6405,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CON ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6319,10 +6424,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CON ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6333,10 +6438,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CO pow_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6348,10 +6455,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC result = fast_is_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6363,10 +6472,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_ result = fast_is_not_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6421,10 +6532,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CON } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6479,10 +6590,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6522,10 +6633,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_C goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6569,10 +6680,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQU goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6583,10 +6694,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CO compare_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_OR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6601,10 +6714,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_ ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_AND_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6619,10 +6732,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6637,10 +6750,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -6651,10 +6764,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CON boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -6686,10 +6801,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_ } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -6699,10 +6816,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -6721,7 +6840,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_AR } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -6807,6 +6926,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -6886,10 +7007,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ fetch_obj_r_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -7007,10 +7130,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC fetch_obj_is_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -7027,7 +7152,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -7036,10 +7161,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CONST_ container = RT_CONSTANT(opline, opline->op1); zend_fetch_dimension_address_LIST_r(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -7161,10 +7287,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_ } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -7195,12 +7323,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); + + HANDLE_EXCEPTION(); } while (0); } @@ -7233,6 +7364,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CONST != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -7243,6 +7375,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_invalid_method_call(object, function_name); + + HANDLE_EXCEPTION(); } } while (0); @@ -7267,6 +7401,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -7290,6 +7425,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (IS_CONST != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -7319,7 +7455,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -7337,6 +7473,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { @@ -7347,6 +7484,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -7379,6 +7517,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -7394,6 +7533,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && @@ -7406,6 +7546,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } if (IS_CONST != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -7452,7 +7593,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -7474,6 +7615,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS * to make sure we don't increase VM size too much. */ if (!(IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); } @@ -7496,6 +7638,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } + if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { if (call_info & ZEND_CALL_CLOSURE) { zend_object_release(ZEND_CLOSURE_OBJECT(func)); @@ -7512,6 +7655,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS zend_type_error("%s(): Argument #1 ($callback) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); + HANDLE_EXCEPTION(); } @@ -7523,7 +7667,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -7535,6 +7679,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONS arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -7551,7 +7696,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONS ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_EX_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -7563,6 +7708,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_CONST_H arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -7575,8 +7721,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_CONST_H goto send_val_by_ref; } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); @@ -7588,7 +7734,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_CONST_H ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; zend_class_constant *c; @@ -7613,6 +7759,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS if (UNEXPECTED(ce == NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } CACHE_PTR(opline->extended_value, ce); @@ -7622,6 +7769,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS if (UNEXPECTED(ce == NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } else { @@ -7639,6 +7787,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } constant_name = Z_STR_P(constant_zv); @@ -7646,6 +7795,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + ZEND_VM_NEXT_OPCODE(); } zv = IS_CONST == IS_CONST @@ -7659,6 +7809,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } @@ -7666,6 +7817,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } @@ -7683,6 +7835,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -7693,6 +7846,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -7700,6 +7854,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -7711,16 +7866,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } while (0); ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -7735,6 +7892,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = RT_CONSTANT(opline, opline->op1); if (IS_CONST == IS_TMP_VAR) { @@ -7807,6 +7965,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -7816,7 +7975,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -7838,7 +7997,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HA } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -7889,6 +8048,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM if (IS_CONST & (IS_CONST|IS_CV)) { /* avoid exception check */ + ZEND_VM_SMART_BRANCH(result, 0); } } else { @@ -7914,10 +8074,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM isset_dim_obj_exit: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -7964,10 +8126,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO isset_object_finish: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7996,10 +8160,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CO } + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8010,7 +8176,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON if (zv) { SAVE_OPLINE(); ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2))); - if (!ce) { + if (EG(exception)) { HANDLE_EXCEPTION(); } } @@ -8019,7 +8185,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *name; @@ -8036,6 +8202,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST zval_ptr_dtor_nogc(&c.value); + + HANDLE_EXCEPTION(); } } @@ -8043,19 +8211,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); c.name = zend_string_copy(Z_STR_P(name)); - if (zend_register_constant(&c) == FAILURE) { + if (zend_register_constant(&c) == NULL) { } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *name; zval *val; - zend_constant c; + zend_constant c, *registered; SAVE_OPLINE(); name = RT_CONSTANT(opline, opline->op1); @@ -8067,6 +8237,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_ zval_ptr_dtor_nogc(&c.value); + + HANDLE_EXCEPTION(); } } @@ -8074,7 +8246,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_ ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); c.name = zend_string_copy(Z_STR_P(name)); - if (zend_register_constant(&c) == FAILURE) { + registered = zend_register_constant(&c); + if (registered == NULL) { + + /* two opcodes used, second one is the data with attributes */ @@ -8082,17 +8257,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_ } HashTable *attributes = Z_PTR_P(get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1)); - zend_constant *registered = zend_get_constant_ptr(c.name); ZEND_ASSERT(attributes != NULL); - ZEND_ASSERT(registered != NULL); zend_constant_add_attributes(registered, attributes); + + /* two opcodes used, second one is the data with attributes */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8149,6 +8324,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = RT_CONSTANT(opline, opline->op1); @@ -8164,6 +8340,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_CONST == IS_CV) { @@ -8184,6 +8361,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -8211,7 +8389,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER ZEND_VM_RETURN(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SWITCH_LONG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op, *jump_zv; @@ -8239,7 +8417,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_ } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SWITCH_STRING_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op, *jump_zv; @@ -8272,7 +8450,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPE } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MATCH_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op, *jump_zv; @@ -8313,7 +8491,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_CONST_ } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IN_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -8340,10 +8518,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find(ht, Z_STR_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); } } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { @@ -8368,6 +8548,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find(ht, Z_STR_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); } } @@ -8377,15 +8558,17 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { + ZEND_VM_SMART_BRANCH(1, 1); } } ZEND_HASH_FOREACH_END(); } + ZEND_VM_SMART_BRANCH(0, 1); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -8420,10 +8603,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -8458,10 +8641,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMP } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -8485,10 +8668,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVARCV_HANDLE } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8506,10 +8689,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVARCV_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8525,10 +8708,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVARCV_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8568,10 +8751,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8611,10 +8794,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8654,10 +8837,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CO goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8701,10 +8884,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8748,10 +8931,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8795,10 +8978,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; zend_class_constant *c; @@ -8931,7 +9114,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -8943,7 +9126,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_NO_OVERFL ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -8955,7 +9138,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_SPEC_CONS ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -8967,7 +9150,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_DOUBLE_SPEC_CO ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8979,7 +9162,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMP ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -8991,7 +9174,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9003,7 +9186,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9015,7 +9198,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_T ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9027,7 +9210,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9039,7 +9222,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9051,7 +9234,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_ ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9063,7 +9246,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9075,7 +9258,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9087,7 +9270,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPE ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9099,7 +9282,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9111,7 +9294,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -9128,6 +9311,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ SAVE_OPLINE(); zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); @@ -9136,6 +9320,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_NEXT_OPCODE(); @@ -9155,6 +9340,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ } zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -9163,10 +9349,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ SAVE_OPLINE(); zend_undefined_offset(offset); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9176,11 +9363,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER( op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); div_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9190,11 +9378,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMPVAR_HANDLER( op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9266,12 +9455,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL } concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9281,11 +9471,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HA op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -9317,10 +9508,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_ } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -9330,10 +9522,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -9352,7 +9545,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -9438,6 +9631,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -9517,10 +9712,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ fetch_obj_r_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -9638,10 +9834,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC fetch_obj_is_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -9658,7 +9855,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -9670,7 +9867,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -9791,11 +9988,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_ } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -9826,12 +10024,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } while (0); } @@ -9874,6 +10074,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_invalid_method_call(object, function_name); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } } while (0); @@ -9950,7 +10151,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -10083,7 +10284,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -10155,7 +10356,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -10170,6 +10371,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = RT_CONSTANT(opline, opline->op1); if (IS_CONST == IS_TMP_VAR) { @@ -10251,7 +10453,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -10273,7 +10475,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_H } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -10349,10 +10551,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON isset_dim_obj_exit: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -10399,10 +10602,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO isset_object_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10432,10 +10636,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TM zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10492,6 +10697,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLE ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = RT_CONSTANT(opline, opline->op1); @@ -10507,6 +10713,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLE } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_CONST == IS_CV) { @@ -10555,7 +10762,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMPVAR_HANDLE ZEND_VM_RETURN(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE zval *varname; @@ -10579,6 +10786,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad if (UNEXPECTED(!name)) { if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + } ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -10641,6 +10849,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + } if (IS_CONST != IS_CONST) { @@ -10656,41 +10865,41 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { int fetch_type = (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -10709,7 +10918,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -10727,6 +10936,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { @@ -10737,6 +10947,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -10769,6 +10980,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -10784,6 +10996,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && @@ -10796,6 +11009,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } if (IS_UNUSED != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -10842,7 +11056,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { if (IS_CONST == IS_UNUSED) { SAVE_OPLINE(); @@ -10909,7 +11123,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -10921,6 +11135,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONS arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -10937,7 +11152,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONS ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -10949,6 +11164,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_ arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -10961,8 +11177,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_ goto send_val_by_ref; } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); @@ -10974,7 +11190,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -10986,6 +11202,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_C arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -10998,8 +11215,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_C goto send_val_by_ref; } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = RT_CONSTANT(opline, opline->op1); ZVAL_COPY_VALUE(arg, value); @@ -11011,7 +11228,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NEW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *result; @@ -11080,7 +11297,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_UNUSED_HANDLER( ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -11095,6 +11312,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = RT_CONSTANT(opline, opline->op1); if (IS_CONST == IS_TMP_VAR) { @@ -11167,6 +11385,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -11176,7 +11395,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -11198,7 +11417,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_H } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varname; @@ -11221,6 +11440,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA name = zval_try_get_tmp_string(varname, &tmp_name); if (UNEXPECTED(!name)) { + HANDLE_EXCEPTION(); } } @@ -11232,11 +11452,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA zend_tmp_string_release(tmp_name); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -11260,6 +11481,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U zend_tmp_string_release(tmp_name); } + if (!value) { result = (opline->extended_value & ZEND_ISEMPTY); } else { @@ -11280,7 +11502,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11337,6 +11559,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = RT_CONSTANT(opline, opline->op1); @@ -11352,6 +11575,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_CONST == IS_CV) { @@ -11372,6 +11596,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -11399,7 +11624,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE ZEND_VM_RETURN(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op; @@ -11410,7 +11635,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_ HANDLE_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COUNT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -11462,10 +11687,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_ ZVAL_LONG(EX_VAR(opline->result.var), count); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_CLASS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11504,11 +11730,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CO break; } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -11523,10 +11750,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CON ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_array *ht; @@ -11603,7 +11831,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSE } /* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -11659,7 +11887,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_PARENT_PROPERTY_HOOK_CALL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -11670,10 +11898,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND div_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -11684,10 +11914,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND pow_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -11760,11 +11992,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z concat_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -11775,10 +12009,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CV_HANDLE compare_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -11810,10 +12046,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HAND } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -11823,10 +12061,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HAN zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -11845,7 +12085,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -11931,6 +12171,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -12010,10 +12252,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ fetch_obj_r_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -12131,10 +12375,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC fetch_obj_is_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -12151,7 +12397,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_AR } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -12160,10 +12406,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_CONST_CV_HAN container = RT_CONSTANT(opline, opline->op1); zend_fetch_dimension_address_LIST_r(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -12285,10 +12532,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -12319,12 +12568,15 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); + + HANDLE_EXCEPTION(); } while (0); } @@ -12357,6 +12609,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CV != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -12367,6 +12620,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_invalid_method_call(object, function_name); + + HANDLE_EXCEPTION(); } } while (0); @@ -12391,6 +12646,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -12414,6 +12670,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ if (IS_CV != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -12443,7 +12700,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -12461,6 +12718,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { @@ -12471,6 +12729,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -12503,6 +12762,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -12518,6 +12778,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && @@ -12530,6 +12791,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C } if (IS_CV != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -12576,7 +12838,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -12598,6 +12860,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H * to make sure we don't increase VM size too much. */ if (!(IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); } @@ -12620,6 +12883,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; } + if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { if (call_info & ZEND_CALL_CLOSURE) { zend_object_release(ZEND_CLOSURE_OBJECT(func)); @@ -12636,6 +12900,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H zend_type_error("%s(): Argument #1 ($callback) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); efree(error); + HANDLE_EXCEPTION(); } @@ -12647,7 +12912,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -12662,6 +12927,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = RT_CONSTANT(opline, opline->op1); if (IS_CONST == IS_TMP_VAR) { @@ -12734,6 +13000,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -12743,7 +13010,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -12765,7 +13032,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDL } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -12816,6 +13083,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON if (IS_CONST & (IS_CONST|IS_CV)) { /* avoid exception check */ + ZEND_VM_SMART_BRANCH(result, 0); } } else { @@ -12841,10 +13109,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON isset_dim_obj_exit: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -12891,10 +13161,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PRO isset_object_finish: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -12923,10 +13195,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV } + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -12983,6 +13257,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = RT_CONSTANT(opline, opline->op1); @@ -12998,6 +13273,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_CONST == IS_CV) { @@ -13018,6 +13294,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -13045,7 +13322,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE ZEND_VM_RETURN(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_NOT_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -13056,10 +13333,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_not_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -13069,7 +13346,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_LONG_SPE ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -13079,7 +13356,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_DOUBLE_S ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -13089,7 +13366,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_NOREF_SP ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13124,10 +13401,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13162,10 +13439,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13203,10 +13480,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLE } } - ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13230,10 +13507,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_CONST_HANDLE } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13251,10 +13528,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_CONST_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13270,10 +13547,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_CONST_HANDLER ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13313,10 +13590,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13356,10 +13633,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13399,10 +13676,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13446,10 +13723,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13493,10 +13770,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13540,10 +13817,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_OR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13558,10 +13835,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARC ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_AND_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13576,10 +13853,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_XOR_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13594,10 +13871,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -13606,10 +13883,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CON container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_LIST_r(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op, *jump_zv; @@ -13637,7 +13915,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONS } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op, *jump_zv; @@ -13670,7 +13948,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SWITCH_STRING_SPEC_TMPVARCV_CO } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MATCH_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op, *jump_zv; @@ -13711,7 +13989,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_SPEC_TMPVARCV_CONST_HAND } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13723,7 +14001,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_NO_OVERFL ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13735,7 +14013,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13747,7 +14025,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_DOUBLE_SPEC_TM ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13759,7 +14037,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_NO_OVERFL ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13771,7 +14049,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13783,7 +14061,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_DOUBLE_SPEC_TM ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13795,7 +14073,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_NO_OVERFL ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13809,7 +14087,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -13821,7 +14099,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_DOUBLE_SPEC_TM ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13833,7 +14111,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CO ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13845,7 +14123,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13857,7 +14135,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13869,7 +14147,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_ ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13881,7 +14159,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13893,7 +14171,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13905,7 +14183,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARC ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13917,7 +14195,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13929,7 +14207,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13941,7 +14219,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVA ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13953,7 +14231,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -13965,7 +14243,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -13975,10 +14253,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_ result = Z_TYPE_P(op1) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(op1)) == 0; FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -13988,10 +14267,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_ result = Z_TYPE_P(op1) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(op1)) == 0; FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -14001,10 +14281,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_ result = Z_TYPE_P(op1) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(op1)) == 0; FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -14014,10 +14295,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_S result = Z_TYPE_P(op1) != IS_ARRAY || zend_hash_num_elements(Z_ARR_P(op1)) > 0; FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -14027,10 +14309,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_S result = Z_TYPE_P(op1) != IS_ARRAY || zend_hash_num_elements(Z_ARR_P(op1)) > 0; FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -14040,10 +14323,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_S result = Z_TYPE_P(op1) != IS_ARRAY || zend_hash_num_elements(Z_ARR_P(op1)) > 0; FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14055,7 +14339,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_ ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14067,7 +14351,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14079,7 +14363,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14091,7 +14375,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARC ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14103,7 +14387,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14115,7 +14399,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14127,7 +14411,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_ ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14139,7 +14423,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14151,7 +14435,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14163,7 +14447,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPE ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14175,7 +14459,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14187,7 +14471,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14222,10 +14506,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14260,10 +14544,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_SPEC_TMPVARCV_ } } - ZEND_VM_TAIL_CALL(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14301,10 +14585,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_HAN } } - ZEND_VM_TAIL_CALL(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14328,10 +14612,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_HAN } } - ZEND_VM_TAIL_CALL(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14349,10 +14633,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVARCV_TMPVARCV_HAND ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14368,10 +14652,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVARCV_TMPVARCV_HAND ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14411,10 +14695,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVA goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14454,10 +14738,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14497,10 +14781,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TM goto is_smaller_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14544,10 +14828,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14591,10 +14875,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14638,10 +14922,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA goto is_smaller_or_equal_double; } } - ZEND_VM_TAIL_CALL(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14656,10 +14940,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVARC ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14674,10 +14958,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14692,10 +14976,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_TAIL_CALL(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14707,7 +14991,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_NO_OVERFL ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14719,7 +15003,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_LONG_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14731,7 +15015,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_DOUBLE_SPEC_TM ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14743,7 +15027,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_NO_OVERFL ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14755,7 +15039,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_LONG_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14767,7 +15051,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SUB_DOUBLE_SPEC_TM ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14779,7 +15063,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_NO_OVERFL ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14793,7 +15077,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_LONG_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2, *result; @@ -14805,7 +15089,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MUL_DOUBLE_SPEC_TM ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14817,7 +15101,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TM ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14829,7 +15113,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14841,7 +15125,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_LONG_SPEC ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14853,7 +15137,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_ ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14865,7 +15149,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14877,7 +15161,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_DOUBLE_SP ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14889,7 +15173,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARC ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14901,7 +15185,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14913,7 +15197,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_LONG_ ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14925,7 +15209,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVA ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14937,7 +15221,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14949,7 +15233,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_DOUBL ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14961,7 +15245,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_ ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14973,7 +15257,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14985,7 +15269,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_LONG_SP ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -14997,7 +15281,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARC ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15009,7 +15293,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15021,7 +15305,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_DOUBLE_ ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15033,7 +15317,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_ ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15045,7 +15329,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15057,7 +15341,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15069,7 +15353,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPE ZEND_VM_SMART_BRANCH_NONE(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15081,7 +15365,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPZ(result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15093,7 +15377,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUA ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -15105,7 +15389,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMP ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op; @@ -15116,7 +15400,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUS HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -15125,10 +15409,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_ container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_LIST_r(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -15154,7 +15439,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *z; @@ -15183,7 +15468,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -15217,7 +15502,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_H ZEND_VM_JMP(opline); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -15251,7 +15536,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_ ZEND_VM_JMP(opline); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -15287,7 +15572,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZE ZEND_VM_JMP(opline); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -15322,7 +15607,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(Z ZEND_VM_JMP(opline); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -15331,7 +15616,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FREE_SPEC_TMPVAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *var; USE_OPLINE @@ -15356,7 +15641,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FREE_SPEC_TMPVA ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_THROW_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -15392,7 +15677,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMPVAR_HANDLER(ZEND HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -15418,7 +15703,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *obj; @@ -15430,7 +15715,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND SAVE_OPLINE(); obj = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. */ + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ do { if ((IS_TMP_VAR|IS_VAR) == IS_CONST || @@ -15467,14 +15753,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { scope = EX(func)->op_array.scope; - if (clone->common.scope != scope) { - if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_wrong_clone_call(clone, scope); - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -15484,7 +15768,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_op_array *new_op_array; @@ -15544,6 +15828,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); + if (EXPECTED(zend_execute_ex == execute_ex)) { zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_ENTER(); @@ -15567,7 +15852,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); @@ -15669,7 +15954,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -15731,7 +16016,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_TYPE_CHECK_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -15767,7 +16052,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TM } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { uint32_t fetch_type; zend_class_entry *called_scope, *scope; @@ -15829,7 +16114,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_H ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15840,10 +16125,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER( div_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15854,10 +16140,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER( pow_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15930,11 +16217,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL concat_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -15989,10 +16277,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16047,10 +16335,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16105,10 +16393,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16163,10 +16451,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16221,10 +16509,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16279,10 +16567,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16293,10 +16581,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HA compare_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16307,10 +16596,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HAN boolean_xor_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -16341,11 +16631,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_ zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -16354,11 +16645,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -16444,6 +16736,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -16522,11 +16816,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ fetch_obj_r_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -16643,11 +16938,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST fetch_obj_is_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16769,10 +17065,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_ } while (0); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -16808,6 +17105,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); @@ -16841,6 +17139,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CONST != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -16850,6 +17149,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_invalid_method_call(object, function_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } @@ -16875,6 +17175,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -16898,6 +17199,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C if (IS_CONST != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -16927,7 +17229,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -16955,7 +17257,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -16996,6 +17298,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (result) { goto case_true; } else { @@ -17003,10 +17306,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -17057,6 +17360,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { /* avoid exception check */ + ZEND_VM_SMART_BRANCH(result, 0); } } else { @@ -17081,11 +17385,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP isset_dim_obj_exit: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -17131,11 +17436,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -17163,11 +17469,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_C result = 0; } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -17212,7 +17519,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_H ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -17267,7 +17574,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -17322,7 +17629,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17336,7 +17643,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17350,7 +17657,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17427,7 +17734,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17482,10 +17789,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17540,10 +17847,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17598,10 +17905,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17656,10 +17963,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17714,10 +18021,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17772,10 +18079,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17789,7 +18096,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -17803,7 +18110,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -17838,7 +18145,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -17851,7 +18158,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -17937,6 +18244,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -18019,7 +18328,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -18140,7 +18449,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -18265,7 +18574,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -18420,7 +18729,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -18468,10 +18777,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -18550,7 +18859,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -18600,7 +18909,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -18633,7 +18942,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_T ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -18678,7 +18987,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HAN ZEND_VM_SMART_BRANCH(result, 1); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE zval *varname; @@ -18779,41 +19088,41 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { int fetch_type = (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -18841,7 +19150,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMPV ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varname; @@ -18879,7 +19188,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -18924,7 +19233,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_ } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -18969,7 +19278,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_ ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -19024,7 +19333,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_array *ht = Z_ARRVAL_P(_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)); @@ -19039,7 +19348,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -19082,7 +19391,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_H } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -19091,7 +19400,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_HA ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -19102,10 +19411,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEN div_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -19116,10 +19426,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEN pow_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -19192,11 +19503,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER( concat_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -19207,10 +19519,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDL compare_function(EX_VAR(opline->result.var), op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -19241,11 +19554,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HAN zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -19254,11 +19568,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HA container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -19344,6 +19659,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -19422,11 +19739,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN fetch_obj_r_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -19543,11 +19861,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA fetch_obj_is_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -19669,10 +19988,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN } while (0); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -19708,6 +20028,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } while (0); @@ -19741,6 +20062,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CV != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -19750,6 +20072,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } zend_invalid_method_call(object, function_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); HANDLE_EXCEPTION(); } @@ -19775,6 +20098,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -19798,6 +20122,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C if (IS_CV != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -19827,7 +20152,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -19868,6 +20193,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (result) { goto case_true; } else { @@ -19875,10 +20201,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE } } } - ZEND_VM_TAIL_CALL(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -19929,6 +20255,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { /* avoid exception check */ + ZEND_VM_SMART_BRANCH(result, 0); } } else { @@ -19953,11 +20280,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP isset_dim_obj_exit: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -20003,11 +20331,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -20035,19 +20364,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_C result = 0; } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -20113,19 +20445,24 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HA + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + SAVE_OPLINE(); return_value = EX(return_value); + do { if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -20177,10 +20514,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER } while (0); + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval; @@ -20216,6 +20555,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HAND } } + EG(current_execute_data) = EX(prev_execute_data); /* Close the generator to free up resources */ @@ -20225,7 +20565,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HAND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; @@ -20246,7 +20586,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -20279,6 +20619,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -20294,7 +20635,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *result; @@ -20310,6 +20651,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE } Z_FE_POS_P(result) = 0; + ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { zend_object *zobj = Z_OBJ_P(array_ptr); @@ -20319,6 +20661,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -20343,11 +20686,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(result) = (uint32_t) -1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); @@ -20370,7 +20715,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZE } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *array_ref; @@ -20406,6 +20751,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { if (!Z_OBJCE_P(array_ptr)->get_iterator) { @@ -20416,6 +20762,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -20442,11 +20789,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); @@ -20468,7 +20817,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(Z } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -20479,7 +20828,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(Z ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -20526,7 +20875,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -20567,7 +20916,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_NULL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val, *result; @@ -20611,7 +20960,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_TMP_ ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -20649,7 +20998,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -20661,10 +21010,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA result = fast_is_identical_function(op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -20675,10 +21025,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CONST_HAN op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -20690,10 +21041,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS result = fast_is_not_identical_function(op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -20712,7 +21064,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CO } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -20729,7 +21081,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CO } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -20758,13 +21110,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLE } rope[opline->extended_value] = zval_get_string_func(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -20793,6 +21146,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE } rope[opline->extended_value] = zval_get_string_func(var); + if (UNEXPECTED(EG(exception))) { for (i = 0; i <= opline->extended_value; i++) { zend_string_release_ex(rope[i], 0); @@ -20824,7 +21178,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -20848,8 +21202,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HAN goto send_val_by_ref; } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(arg, value); @@ -20861,7 +21215,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HAN ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -20948,6 +21302,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -20957,7 +21312,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -20979,7 +21334,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HAND } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -21052,6 +21407,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CV) { @@ -21072,6 +21428,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -21099,7 +21456,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -21171,7 +21528,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLE ZEND_VM_SMART_BRANCH(0, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -21190,7 +21547,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TM } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -21207,7 +21564,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TM } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -21242,7 +21599,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -21302,7 +21659,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -21398,7 +21755,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -21420,7 +21777,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HAN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -21493,6 +21850,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER( } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CV) { @@ -21541,7 +21899,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER( ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -21556,7 +21914,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -21570,7 +21928,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDL ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -21585,7 +21943,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_ ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -21599,7 +21957,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDL ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -21618,7 +21976,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { if (IS_TMP_VAR == IS_UNUSED) { SAVE_OPLINE(); @@ -21685,7 +22043,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -21709,8 +22067,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HA goto send_val_by_ref; } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(arg, value); @@ -21722,7 +22080,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HA ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value, *arg; @@ -21746,8 +22104,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_T goto send_val_by_ref; } } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { -send_val_by_ref: - ZEND_VM_TAIL_CALL(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); } value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); ZVAL_COPY_VALUE(arg, value); @@ -21759,7 +22117,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_T ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -21846,6 +22204,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -21855,7 +22214,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -21877,7 +22236,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HAN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -21950,6 +22309,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CV) { @@ -21970,6 +22330,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -21997,7 +22358,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -22015,7 +22376,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDL ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -22026,10 +22387,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLE op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -22048,7 +22410,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -22065,7 +22427,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -22094,13 +22456,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(Z } rope[opline->extended_value] = zval_get_string_func(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -22129,6 +22492,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z } rope[opline->extended_value] = zval_get_string_func(var); + if (UNEXPECTED(EG(exception))) { for (i = 0; i <= opline->extended_value; i++) { zend_string_release_ex(rope[i], 0); @@ -22160,7 +22524,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -22247,6 +22611,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -22256,7 +22621,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -22278,7 +22643,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -22351,6 +22716,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_TMP_VAR == IS_CV) { @@ -22371,6 +22737,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -22398,7 +22765,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *closure, *var; @@ -22430,7 +22797,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDL ZEND_VM_NEXT_OPCODE(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22463,7 +22830,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22481,7 +22848,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_R ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22499,7 +22866,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_R ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22533,7 +22900,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22551,7 +22918,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_R ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22569,7 +22936,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_R ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22601,7 +22968,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22617,7 +22984,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_ ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22649,7 +23016,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -22665,15 +23032,17 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_ ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -22739,19 +23108,24 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HA + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + SAVE_OPLINE(); return_value = EX(return_value); + do { if ((IS_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -22803,10 +23177,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER } while (0); + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval; @@ -22842,6 +23218,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND } } + EG(current_execute_data) = EX(prev_execute_data); /* Close the generator to free up resources */ @@ -22851,7 +23228,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; @@ -22872,7 +23249,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -22921,7 +23298,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *result; @@ -22998,7 +23375,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_VAR_HANDLER(ZE } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *array_ref; @@ -23097,7 +23474,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_VAR_HANDLER(Z } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array; @@ -23177,7 +23554,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VA } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array; @@ -23379,7 +23756,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -23426,7 +23803,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -23467,7 +23844,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_NULL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val, *result; @@ -23511,7 +23888,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_VAR_ ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -23549,7 +23926,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_SIMPLE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -23566,7 +23943,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SP ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -23578,10 +23955,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA result = fast_is_identical_function(op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -23592,10 +23970,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CONST_HAN op2 = RT_CONSTANT(opline, opline->op2); result = fast_is_identical_function(op1, op2); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -23607,10 +23986,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS result = fast_is_not_identical_function(op1, op2); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -23697,13 +24077,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_H FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -23799,11 +24180,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H } } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -23829,11 +24211,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CONST_HANDL ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -23893,11 +24276,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HAN } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -23955,11 +24339,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HA } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -23968,13 +24353,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HAN container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -23983,13 +24369,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HA container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -24008,7 +24395,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CO } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -24017,13 +24404,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -24038,13 +24426,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HAN ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -24055,13 +24444,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HA result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -24078,7 +24468,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CO } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -24089,13 +24479,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim; @@ -24114,10 +24505,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CONST_HA zend_fetch_dimension_address_W(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -24240,6 +24632,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -24260,18 +24653,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -24419,13 +24814,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -24573,13 +24969,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -24702,6 +25099,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -24722,18 +25120,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -24831,6 +25231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -24838,12 +25239,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -24851,6 +25254,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = RT_CONSTANT(opline, opline->op2); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -24872,6 +25276,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -24879,13 +25284,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } if (IS_CONST != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25032,13 +25438,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } if (IS_CONST != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25185,13 +25592,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } if (IS_CONST != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -25289,6 +25697,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -25296,12 +25705,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -25309,6 +25720,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = RT_CONSTANT(opline, opline->op2); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -25330,6 +25742,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -25337,13 +25750,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } if (IS_CONST != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -25372,7 +25786,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -25401,7 +25815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -25433,12 +25847,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -25471,11 +25886,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -25493,6 +25910,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { @@ -25503,6 +25921,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -25535,6 +25954,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -25550,6 +25970,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && @@ -25562,6 +25983,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } if (IS_CONST != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -25608,7 +26030,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -25655,7 +26077,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -25686,7 +26108,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -25754,7 +26176,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CO ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_REF_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -25784,7 +26206,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_CONST_HANDLE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -25850,7 +26272,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_CONST_HAN ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -25901,7 +26323,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; zend_class_constant *c; @@ -25926,6 +26348,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (UNEXPECTED(ce == NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } CACHE_PTR(opline->extended_value, ce); @@ -25935,6 +26358,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (UNEXPECTED(ce == NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } else { @@ -25952,6 +26376,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } constant_name = Z_STR_P(constant_zv); @@ -25959,6 +26384,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + ZEND_VM_NEXT_OPCODE(); } zv = IS_CONST == IS_CONST @@ -25972,6 +26398,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } @@ -25979,6 +26406,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } @@ -25996,6 +26424,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -26006,6 +26435,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -26013,6 +26443,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -26024,16 +26455,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } while (0); ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -26120,6 +26553,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -26129,7 +26563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -26151,7 +26585,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HAND } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -26238,11 +26672,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDL } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -26282,11 +26717,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26379,6 +26815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -26406,7 +26843,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -26478,7 +26915,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLE ZEND_VM_SMART_BRANCH(0, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; zend_class_constant *c; @@ -26611,7 +27048,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -26704,7 +27141,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_ } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -26805,7 +27242,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -26836,7 +27273,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_HAND ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -26901,7 +27338,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -26964,7 +27401,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -26979,7 +27416,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -26994,7 +27431,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -27013,7 +27450,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -27028,7 +27465,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -27049,7 +27486,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -27066,7 +27503,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -27083,7 +27520,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TM } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -27100,7 +27537,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim; @@ -27123,7 +27560,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -27246,6 +27683,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -27266,6 +27704,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); @@ -27277,7 +27716,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -27431,7 +27870,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -27585,7 +28024,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -27708,6 +28147,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -27728,6 +28168,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); @@ -27739,7 +28180,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -27837,6 +28278,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -27844,12 +28286,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -27857,6 +28301,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -27878,6 +28323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -27891,7 +28337,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -28044,7 +28490,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -28197,7 +28643,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -28295,6 +28741,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -28302,12 +28749,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -28315,6 +28764,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -28336,6 +28786,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -28349,7 +28800,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -28386,7 +28837,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -28419,11 +28870,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -28556,7 +29008,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -28652,7 +29104,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -28674,7 +29126,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HAN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -28766,7 +29218,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HAND ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -28811,7 +29263,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -28932,7 +29384,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMPVAR_HANDLER( ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -28947,7 +29399,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -28961,7 +29413,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_TMP_HANDL ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -28976,7 +29428,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -29005,7 +29457,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNU ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -29034,7 +29486,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -29049,7 +29501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -29063,7 +29515,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_VAR_HANDL ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -29078,7 +29530,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -29107,7 +29559,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -29136,7 +29588,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *variable_ptr; @@ -29175,7 +29627,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -29271,11 +29723,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_ } } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -29284,13 +29737,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HA container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -29299,13 +29753,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_H container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -29324,7 +29779,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -29422,6 +29877,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -29429,12 +29885,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = NULL; value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -29442,6 +29900,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = NULL; + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -29463,6 +29922,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ dim = NULL; assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -29470,13 +29930,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -29623,13 +30084,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -29776,13 +30238,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -29880,6 +30343,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -29887,12 +30351,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = NULL; value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -29900,6 +30366,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = NULL; + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -29921,6 +30388,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ dim = NULL; assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -29928,13 +30396,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } if (IS_UNUSED != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -29952,6 +30421,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { @@ -29962,6 +30432,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -29994,6 +30465,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -30009,6 +30481,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && @@ -30021,6 +30494,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } if (IS_UNUSED != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -30067,7 +30541,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { if (IS_VAR == IS_UNUSED) { SAVE_OPLINE(); @@ -30134,7 +30608,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30181,7 +30655,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30212,7 +30686,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30280,7 +30754,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UN ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30348,7 +30822,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_EX ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30378,7 +30852,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_UNUSED_HANDL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30444,7 +30918,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_HA ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30510,7 +30984,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_V ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30561,7 +31035,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_FUNC_ARG_SPEC ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *result; @@ -30630,7 +31104,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_UNUSED_HANDLER(ZE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -30717,6 +31191,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -30726,7 +31201,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -30748,7 +31223,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HAN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -30763,7 +31238,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -30856,6 +31331,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -30883,7 +31359,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1 = EX_VAR(opline->op1.var); @@ -30916,7 +31392,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_VAR_UNUSED_HANDL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -30934,7 +31410,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_VAR_UNUSED_HANDL ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -30956,7 +31432,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -30967,10 +31443,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_STRICT_SPEC_VAR_CV_HANDLE op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -31057,13 +31534,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_HAND FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -31159,11 +31637,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND } } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -31189,11 +31668,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_VAR_CV_HANDLER( ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -31253,11 +31733,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLE } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -31315,11 +31796,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDL } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -31328,13 +31810,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLE container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -31343,13 +31826,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDL container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -31368,7 +31852,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -31377,13 +31861,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HA container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -31398,13 +31883,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLE ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -31415,13 +31901,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDL result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -31438,7 +31925,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -31449,13 +31936,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HA result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_VAR == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim; @@ -31474,10 +31962,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_W_SPEC_VAR_CV_HANDL zend_fetch_dimension_address_W(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -31600,6 +32089,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -31620,18 +32110,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -31779,13 +32271,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -31933,13 +32426,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -32062,6 +32556,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -32082,18 +32577,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -32191,6 +32688,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -32198,12 +32696,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = EX_VAR(opline->op2.var); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -32211,6 +32711,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -32232,6 +32733,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -32239,13 +32741,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } if (IS_CV != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -32392,13 +32895,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } if (IS_CV != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -32545,13 +33049,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } if (IS_CV != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -32649,6 +33154,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -32656,12 +33162,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = EX_VAR(opline->op2.var); value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -32669,6 +33177,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -32690,6 +33199,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -32697,13 +33207,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } if (IS_CV != IS_UNUSED) { + } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -32732,7 +33243,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -32761,7 +33272,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *variable_ptr; @@ -32795,11 +33306,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER GC_DTOR(garbage); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -32831,12 +33343,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -32869,11 +33382,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -32891,6 +33406,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { @@ -32901,6 +33417,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -32933,6 +33450,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -32948,6 +33466,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && @@ -32960,6 +33479,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V } if (IS_CV != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -33006,7 +33526,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -33093,6 +33613,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -33102,7 +33623,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -33124,7 +33645,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -33211,11 +33732,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER( } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -33255,11 +33777,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER( } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -33352,6 +33875,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -33379,7 +33903,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND ZEND_VM_RETURN(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array; @@ -33447,7 +33971,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array; @@ -33515,7 +34039,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_ } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *obj; @@ -33527,7 +34051,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND SAVE_OPLINE(); obj = &EX(This); - /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. */ + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ do { if (IS_UNUSED == IS_CONST || @@ -33547,6 +34072,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND } zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj)); + HANDLE_EXCEPTION(); } } while (0); @@ -33558,29 +34084,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { scope = EX(func)->op_array.scope; - if (clone->common.scope != scope) { - if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_wrong_clone_call(clone, scope); + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { uint32_t fetch_type; zend_class_entry *called_scope, *scope; @@ -33595,12 +34122,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_H zend_type_error("Cannot use \"::class\" on %s", zend_zval_value_name(op)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -33642,7 +34171,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_H ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -33730,12 +34259,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONS FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -33796,10 +34327,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_ } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -33858,10 +34391,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -33947,6 +34482,8 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -34026,15 +34563,17 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R fetch_obj_r_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -34049,13 +34588,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_ ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -34066,13 +34606,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -34190,10 +34731,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST fetch_obj_is_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -34210,7 +34753,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -34221,13 +34764,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CO result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -34350,6 +34894,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -34370,18 +34915,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -34530,12 +35078,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -34684,12 +35234,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -34812,6 +35364,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -34832,18 +35385,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -34874,12 +35430,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON } + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -34911,11 +35469,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CON + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -34944,13 +35505,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HA } rope[0] = zval_get_string_func(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *class_name; USE_OPLINE @@ -34989,10 +35551,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_ } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -35023,12 +35586,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); + + HANDLE_EXCEPTION(); } while (0); } @@ -35061,6 +35627,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CONST != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -35071,6 +35638,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S zend_invalid_method_call(object, function_name); + + HANDLE_EXCEPTION(); } } while (0); @@ -35095,6 +35664,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -35118,6 +35688,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S if (IS_CONST != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -35147,7 +35718,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -35165,6 +35736,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_CONST != IS_CONST) { @@ -35175,6 +35747,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -35207,6 +35780,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -35222,6 +35796,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_CONST == IS_CONST && @@ -35234,6 +35809,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } if (IS_CONST != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -35280,7 +35856,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE uint32_t arg_num; @@ -35312,7 +35888,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CON ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_constant *c; @@ -35328,7 +35904,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; zend_class_constant *c; @@ -35353,6 +35929,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS if (UNEXPECTED(ce == NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } CACHE_PTR(opline->extended_value, ce); @@ -35362,6 +35939,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS if (UNEXPECTED(ce == NULL)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } else { @@ -35379,6 +35957,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } constant_name = Z_STR_P(constant_zv); @@ -35386,6 +35965,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + ZEND_VM_NEXT_OPCODE(); } zv = IS_CONST == IS_CONST @@ -35399,6 +35979,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } @@ -35406,6 +35987,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } @@ -35423,6 +36005,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS if (EG(exception)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -35433,6 +36016,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -35440,6 +36024,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } @@ -35451,16 +36036,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } while (0); ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -35482,7 +36069,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_H } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -35523,10 +36110,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -35573,10 +36162,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN isset_object_finish: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -35633,6 +36224,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = NULL; @@ -35648,6 +36240,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_UNUSED == IS_CV) { @@ -35668,6 +36261,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -35695,7 +36289,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_class_entry *ce, *scope; zend_class_constant *c; @@ -35828,7 +36422,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -35916,12 +36510,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPV FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -35983,10 +36578,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -36046,10 +36642,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVA zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -36135,6 +36732,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -36214,10 +36813,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR fetch_obj_r_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -36238,7 +36838,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -36255,7 +36855,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -36373,10 +36973,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA fetch_obj_is_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -36393,7 +36994,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -36410,7 +37011,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TM ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -36533,6 +37134,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -36553,18 +37155,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -36713,12 +37317,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -36867,12 +37472,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -36995,6 +37601,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -37015,18 +37622,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -37056,13 +37665,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -37092,13 +37702,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMP zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -37133,7 +37745,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_H ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *class_name; USE_OPLINE @@ -37176,7 +37788,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -37207,12 +37819,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } while (0); } @@ -37255,6 +37869,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T zend_invalid_method_call(object, function_name); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } } while (0); @@ -37331,7 +37946,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -37464,7 +38079,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -37486,7 +38101,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_ } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -37528,10 +38143,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -37578,10 +38194,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN isset_object_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -37638,6 +38255,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDL ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = NULL; @@ -37653,6 +38271,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDL } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_UNUSED == IS_CV) { @@ -37701,7 +38320,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMPVAR_HANDL ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *class_name; USE_OPLINE @@ -37740,10 +38359,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -37761,6 +38381,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_UNUSED != IS_CONST) { @@ -37771,6 +38392,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -37803,6 +38425,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -37818,6 +38441,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_UNUSED == IS_CONST && @@ -37830,6 +38454,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } if (IS_UNUSED != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -37876,7 +38501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { if (IS_UNUSED == IS_UNUSED) { SAVE_OPLINE(); @@ -37943,14 +38568,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } } -static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { SAVE_OPLINE(); zend_verify_never_error(EX(func)); HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE uint32_t arg_num; @@ -37982,7 +38607,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNU ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE uint32_t arg_num; @@ -38014,7 +38639,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_FUNC_ARG_SPE ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38028,7 +38653,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_UNDEF_ARGS_S ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *result; @@ -38097,7 +38722,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_UNUSED_HANDLER ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -38119,7 +38744,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_ } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38176,6 +38801,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = NULL; @@ -38191,6 +38817,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_UNUSED == IS_CV) { @@ -38211,6 +38838,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -38238,7 +38866,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL ZEND_VM_RETURN(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38253,7 +38881,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_SPEC_UN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38263,7 +38891,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUS ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38273,7 +38901,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38312,11 +38940,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_H break; } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38334,7 +38963,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CALLED_CLASS_SPEC_UNUSED_U ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -38342,7 +38971,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUS ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_array *ht; @@ -38419,7 +39048,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUS } /* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -38437,7 +39066,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALLABLE_CONVERT_SPEC_UNUSED_U ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -38457,7 +39086,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_0_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FRAMELESS_ICALL_0_SPEC_OBSERVER_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); @@ -38477,7 +39106,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FRAMELESS_ICALL_0_SPEC_OBSERVE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -38565,12 +39194,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_H FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -38631,10 +39262,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HAN } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -38693,10 +39326,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HA } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -38782,6 +39417,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -38861,10 +39498,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN fetch_obj_r_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -38879,13 +39518,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HAN ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -38896,13 +39536,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HA result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -39020,10 +39661,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA fetch_obj_is_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -39040,7 +39683,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -39051,13 +39694,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_UNUSED == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -39180,6 +39824,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -39200,18 +39845,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -39360,12 +40008,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -39514,12 +40164,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -39642,6 +40294,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -39662,18 +40315,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -39704,12 +40360,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ } + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -39741,11 +40399,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_ + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string **rope; @@ -39774,13 +40435,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDL } rope[0] = zval_get_string_func(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *class_name; USE_OPLINE @@ -39819,10 +40481,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_CV_HAN } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -39853,12 +40516,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); + + HANDLE_EXCEPTION(); } while (0); } @@ -39891,6 +40557,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CV != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -39901,6 +40568,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C zend_invalid_method_call(object, function_name); + + HANDLE_EXCEPTION(); } } while (0); @@ -39925,6 +40594,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -39948,6 +40618,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C if (IS_CV != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -39977,7 +40648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -39995,6 +40666,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } if (IS_CV != IS_CONST) { @@ -40005,6 +40677,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ce = zend_fetch_class(NULL, opline->op1.num); if (UNEXPECTED(ce == NULL)) { + HANDLE_EXCEPTION(); } } else { @@ -40037,6 +40710,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } zend_throw_error(NULL, "Method name must be a string"); + HANDLE_EXCEPTION(); } while (0); } @@ -40052,6 +40726,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U zend_undefined_method(ce, Z_STR_P(function_name)); } + HANDLE_EXCEPTION(); } if (IS_CV == IS_CONST && @@ -40064,6 +40739,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U } if (IS_CV != IS_CONST) { + } } else { if (UNEXPECTED(ce->constructor == NULL)) { @@ -40110,7 +40786,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -40132,7 +40808,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HAND } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -40173,10 +40849,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -40223,10 +40901,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN isset_object_finish: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -40283,6 +40963,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = NULL; @@ -40298,6 +40979,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_UNUSED == IS_CV) { @@ -40318,6 +41000,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -40345,7 +41028,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -40366,12 +41049,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_ SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_pre_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40400,10 +41084,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40421,7 +41106,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RE ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40439,7 +41124,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RE ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_pre_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40469,10 +41154,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40490,7 +41176,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RE ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40508,7 +41194,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RE ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_post_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40536,10 +41222,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel increment_function(var_ptr); } while (0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40555,7 +41242,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_H ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_post_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40583,10 +41270,11 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel decrement_function(var_ptr); } while (0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -40602,7 +41290,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_H ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *z; @@ -40627,10 +41315,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCO zend_string_release_ex(str, 0); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -40664,7 +41353,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDL ZEND_VM_JMP(opline); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -40698,7 +41387,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HAND ZEND_VM_JMP(opline); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -40724,6 +41413,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_O SAVE_OPLINE(); ret = i_zend_is_true(val); + if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline++; @@ -40734,7 +41424,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_O ZEND_VM_JMP(opline); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -40759,6 +41449,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_ SAVE_OPLINE(); ret = i_zend_is_true(val); + if (ret) { ZVAL_TRUE(EX_VAR(opline->result.var)); opline = OP_JMP_ADDR(opline, opline->op2); @@ -40769,15 +41460,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_ ZEND_VM_JMP(opline); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -40843,19 +41536,24 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HAN + + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval_ptr; zval *return_value; + SAVE_OPLINE(); return_value = EX(return_value); + do { if ((IS_CV & (IS_CONST|IS_TMP_VAR)) || (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { @@ -40865,6 +41563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( retval_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (!return_value) { + } else { if (IS_CV == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { ZVAL_COPY_VALUE(return_value, retval_ptr); @@ -40889,6 +41588,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( ZVAL_NEW_REF(return_value, retval_ptr); } else { + } break; } @@ -40903,13 +41603,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( ZVAL_REF(return_value, Z_REF_P(retval_ptr)); } + } while (0); + + ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *retval; @@ -40945,6 +41648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CV_HANDL } } + EG(current_execute_data) = EX(prev_execute_data); /* Close the generator to free up resources */ @@ -40954,7 +41658,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CV_HANDL ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -40978,6 +41682,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC } zend_throw_error(NULL, "Can only throw objects"); + HANDLE_EXCEPTION(); } } while (0); @@ -40987,10 +41692,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC zend_throw_exception_object(value); zend_exception_restore(); + HANDLE_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *arg, *param; @@ -41007,10 +41713,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND ZVAL_COPY(param, arg); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val; @@ -41031,12 +41738,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *obj; @@ -41048,7 +41756,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC SAVE_OPLINE(); obj = EX_VAR(opline->op1.var); - /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. */ + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ do { if (IS_CV == IS_CONST || @@ -41068,6 +41777,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC } zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj)); + HANDLE_EXCEPTION(); } } while (0); @@ -41079,29 +41789,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC if (UNEXPECTED(clone_call == NULL)) { zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { scope = EX(func)->op_array.scope; - if (clone->common.scope != scope) { - if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE) - || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { - zend_wrong_clone_call(clone, scope); + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); - ZVAL_UNDEF(EX_VAR(opline->result.var)); - HANDLE_EXCEPTION(); - } + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -41134,6 +41845,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -41145,10 +41857,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO } } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_op_array *new_op_array; @@ -41159,6 +41872,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); if (UNEXPECTED(EG(exception) != NULL)) { + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { destroy_op_array(new_op_array); efree_size(new_op_array, sizeof(zend_op_array)); @@ -41208,8 +41922,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); + if (EXPECTED(zend_execute_ex == execute_ex)) { + ZEND_VM_ENTER(); } else { ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); @@ -41223,15 +41939,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE if (UNEXPECTED(EG(exception) != NULL)) { zend_rethrow_exception(execute_data); + UNDEF_RESULT(); HANDLE_EXCEPTION(); } } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *result; @@ -41247,6 +41965,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN } Z_FE_POS_P(result) = 0; + ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { zend_object *zobj = Z_OBJ_P(array_ptr); @@ -41256,6 +41975,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -41280,15 +42000,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(result) = (uint32_t) -1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -41302,11 +42025,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_R_SPEC_CV_HANDLER(ZEN ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *array_ptr, *array_ref; @@ -41342,6 +42066,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { if (!Z_OBJCE_P(array_ptr)->get_iterator) { @@ -41352,6 +42077,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); + HANDLE_EXCEPTION(); } } @@ -41378,15 +42104,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { HANDLE_EXCEPTION(); } else if (is_empty) { @@ -41400,11 +42129,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_RESET_RW_SPEC_CV_HANDLER(ZE ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -41425,6 +42155,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_O if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -41447,10 +42178,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_O ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -41491,7 +42223,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_JMP_NULL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *val, *result; @@ -41504,6 +42236,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_CV_H val = Z_REFVAL_P(val); if (Z_TYPE_P(val) <= IS_NULL) { + break; } } @@ -41535,7 +42268,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_NULL_SPEC_CV_H ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -41573,7 +42306,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); @@ -41585,6 +42318,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -41597,6 +42331,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN } Z_FE_POS(generator->values) = 0; + } else if (IS_CV != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { zend_class_entry *ce = Z_OBJCE_P(val); if (ce == zend_ce_generator) { @@ -41604,6 +42339,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN Z_ADDREF_P(val); + if (UNEXPECTED(new_gen->execute_data == NULL)) { zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); zval_ptr_dtor(val); @@ -41627,6 +42363,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN } else { zend_object_iterator *iter = ce->get_iterator(ce, val, 0); + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { if (!EG(exception)) { zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); @@ -41653,6 +42390,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN } else { zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + UNDEF_RESULT(); HANDLE_EXCEPTION(); } @@ -41673,7 +42411,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -41693,6 +42431,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + ZEND_VM_NEXT_OPCODE(); } } @@ -41732,10 +42471,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP } while (0); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -41765,13 +42505,14 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV if (IS_CV & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); + ZEND_VM_SMART_BRANCH(result, 1); } else { ZEND_VM_SMART_BRANCH(result, 0); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { uint32_t fetch_type; zend_class_entry *called_scope, *scope; @@ -41786,12 +42527,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDL zend_type_error("Cannot use \"::class\" on %s", zend_zval_value_name(op)); ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -41833,7 +42576,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_CV_HANDL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BIND_STATIC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE HashTable *ht; @@ -41886,7 +42629,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_HANDLER(ZE ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE HashTable *ht; @@ -41914,7 +42657,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_C } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -41927,7 +42670,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_NO_OV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -41940,7 +42683,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_NO_OV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -41953,7 +42696,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_SPEC_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -41966,7 +42709,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_LONG_SPEC_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -41979,7 +42722,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_NO_OV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -41992,7 +42735,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_NO_OV ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42005,7 +42748,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_SPEC_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42018,7 +42761,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_LONG_SPEC_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42029,7 +42772,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_LONG_NO_O ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_LONG_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_LONG_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42040,7 +42783,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_LONG_SPEC ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42051,7 +42794,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_LONG_NO_O ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_LONG_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_DEC_LONG_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42062,7 +42805,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_LONG_SPEC ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_SIMPLE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -42079,7 +42822,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SIMPLE_SP ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42090,10 +42833,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND div_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42104,10 +42849,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND pow_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42180,11 +42927,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z concat_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42196,10 +42945,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN result = fast_is_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42211,10 +42962,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST result = fast_is_not_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42269,10 +43022,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42327,10 +43080,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_HA } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42385,10 +43138,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_H } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42443,10 +43196,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42501,10 +43254,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42559,10 +43312,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMP } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42573,10 +43326,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLE compare_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -42587,10 +43342,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -42678,12 +43435,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_HA FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42780,10 +43539,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA } + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -42810,10 +43571,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CONST_HANDLE } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -42874,10 +43637,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HAND } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -42936,10 +43701,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HAN } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -42971,10 +43738,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HAND } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -42983,13 +43752,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HAND container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -42998,13 +43768,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HAN container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -43014,10 +43785,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HAN zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -43036,7 +43809,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CON } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -43045,13 +43818,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_ container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -43137,6 +43911,8 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -43216,15 +43992,17 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R fetch_obj_r_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CV_CONST_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -43239,13 +44017,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HAND ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -43256,13 +44035,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HAN result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -43380,10 +44160,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN fetch_obj_is_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -43400,7 +44182,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CON } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -43411,13 +44193,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_ result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -43540,6 +44323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -43560,18 +44344,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -43720,12 +44507,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -43874,12 +44663,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -44002,6 +44793,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -44022,18 +44814,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -44131,6 +44926,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -44138,12 +44934,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -44151,6 +44949,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = RT_CONSTANT(opline, opline->op2); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -44172,6 +44971,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -44179,13 +44979,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } if (IS_CONST != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -44332,13 +45134,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } if (IS_CONST != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -44485,13 +45289,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } if (IS_CONST != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -44589,6 +45395,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -44596,12 +45403,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = RT_CONSTANT(opline, opline->op2); value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -44609,6 +45418,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = RT_CONSTANT(opline, opline->op2); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -44630,6 +45440,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA dim = RT_CONSTANT(opline, opline->op2); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -44637,13 +45448,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } if (IS_CONST != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -44667,12 +45480,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -44696,12 +45510,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -44732,12 +45547,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O } + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -44769,11 +45586,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_O + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -44895,10 +45715,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -44929,12 +45751,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); + + HANDLE_EXCEPTION(); } while (0); } @@ -44967,6 +45792,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CONST != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -44977,6 +45803,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S zend_invalid_method_call(object, function_name); + + HANDLE_EXCEPTION(); } } while (0); @@ -45001,6 +45829,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -45024,6 +45853,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S if (IS_CONST != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -45053,7 +45883,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_S ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -45065,6 +45895,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_C arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -45100,7 +45931,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_REF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -45112,6 +45943,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_CONST_HANDLER arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -45126,10 +45958,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_CONST_HANDLER } ZVAL_REF(arg, Z_REF_P(varptr)); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -45141,6 +45974,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_CONST_HAND arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -45162,6 +45996,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_CONST_HAND } ZVAL_REF(arg, Z_REF_P(varptr)); + ZEND_VM_NEXT_OPCODE(); } @@ -45194,7 +46029,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_CONST_HAND ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -45209,6 +46044,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_TMP_VAR) { @@ -45281,6 +46117,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -45290,7 +46127,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -45312,7 +46149,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDL } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -45400,10 +46237,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLE } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -45444,10 +46283,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -45498,6 +46339,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_ if (IS_CV & (IS_CONST|IS_CV)) { /* avoid exception check */ + ZEND_VM_SMART_BRANCH(result, 0); } } else { @@ -45523,10 +46365,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_ isset_dim_obj_exit: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -45573,10 +46417,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV isset_object_finish: + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -45605,10 +46451,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST } + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -45633,6 +46481,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDL ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -45650,10 +46499,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDL result = 0; } + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -45710,6 +46560,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -45725,6 +46576,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_CV == IS_CV) { @@ -45745,6 +46597,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -45772,7 +46625,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE ZEND_VM_RETURN(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_string *varname; @@ -45852,7 +46705,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -45879,10 +46732,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find(ht, Z_STR_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); } } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { @@ -45907,6 +46762,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { result = zend_hash_find(ht, Z_STR_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); } } @@ -45916,15 +46772,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER ZVAL_STR(&key_tmp, key); if (zend_compare(op1, &key_tmp) == 0) { + ZEND_VM_SMART_BRANCH(1, 1); } } ZEND_HASH_FOREACH_END(); } + ZEND_VM_SMART_BRANCH(0, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */ /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */ @@ -45940,7 +46798,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_C ZEND_VM_SMART_BRANCH(result, 0); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -45953,7 +46811,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_ ZEND_VM_SMART_BRANCH(!result, 0); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -45970,6 +46828,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ SAVE_OPLINE(); zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); @@ -45978,6 +46837,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (IS_CV & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_NEXT_OPCODE(); @@ -45997,6 +46857,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ } zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46005,10 +46866,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ SAVE_OPLINE(); zend_undefined_offset(offset); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -46025,6 +46887,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ SAVE_OPLINE(); zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); @@ -46033,6 +46896,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (IS_CV & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { ZEND_VM_NEXT_OPCODE(); @@ -46052,6 +46916,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ } zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46060,10 +46925,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ SAVE_OPLINE(); zend_undefined_offset(offset); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46073,11 +46939,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEN op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); div_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46087,11 +46954,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_TMPVAR_HANDLER(ZEN op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); pow_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46163,12 +47031,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER( } concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46223,10 +47092,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLE } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46281,10 +47150,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_H } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46339,10 +47208,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_ } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46397,10 +47266,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HA } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46455,10 +47324,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46513,10 +47382,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JM } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46526,11 +47395,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDL op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); compare_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -46540,11 +47410,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLE op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -46632,12 +47503,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_H FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -46735,10 +47607,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -46766,10 +47639,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_HANDL zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -46831,10 +47705,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HAN zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -46894,10 +47769,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HA zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -46929,10 +47805,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HAN } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -46947,7 +47824,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HAN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -46962,7 +47839,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -46972,10 +47849,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HA zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -46994,7 +47872,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -47009,7 +47887,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -47095,6 +47973,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -47174,10 +48054,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN fetch_obj_r_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -47198,7 +48079,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HAN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -47215,7 +48096,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -47333,10 +48214,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA fetch_obj_is_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -47353,7 +48235,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -47370,7 +48252,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -47493,6 +48375,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -47513,18 +48396,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -47673,12 +48558,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -47827,12 +48713,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -47955,6 +48842,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -47975,18 +48863,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -48084,6 +48974,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -48091,12 +48982,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -48104,6 +48997,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -48125,6 +49019,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -48134,11 +49029,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -48287,11 +49183,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -48440,11 +49337,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -48542,6 +49440,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -48549,12 +49448,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -48562,6 +49463,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -48583,6 +49485,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -48592,11 +49495,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -48626,13 +49530,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -48662,13 +49567,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_ zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -48789,11 +49696,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN } } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -48824,12 +49732,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } while (0); } @@ -48872,6 +49782,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA zend_invalid_method_call(object, function_name); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); } } while (0); @@ -48948,7 +49859,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -48963,6 +49874,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_TMP_VAR) { @@ -49044,7 +49956,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -49066,7 +49978,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HAND } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -49155,10 +50067,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -49200,10 +50113,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -49279,10 +50193,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_ isset_dim_obj_exit: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -49329,10 +50244,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV isset_object_finish: zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -49362,10 +50278,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVA zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -49422,6 +50339,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(Z ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -49437,6 +50355,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(Z } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_CV == IS_CV) { @@ -49485,7 +50404,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMPVAR_HANDLER(Z ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -49496,11 +50415,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -49511,11 +50431,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -49539,12 +50460,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUS value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -49568,12 +50490,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -49584,11 +50507,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -49599,11 +50523,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -49627,12 +50552,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUS value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -49656,12 +50582,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *variable_ptr; @@ -49697,10 +50624,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -49725,6 +50653,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -49742,10 +50671,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER result = 0; } + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -49842,10 +50772,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H } + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV_EX zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE zval *varname; @@ -49869,6 +50801,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad if (UNEXPECTED(!name)) { if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + } ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); @@ -49931,6 +50864,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + } if (IS_CV != IS_CONST) { @@ -49946,41 +50880,41 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_ad ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { int fetch_type = (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? BP_VAR_W : BP_VAR_R; - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -49989,13 +50923,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HAN container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -50004,13 +50939,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HA container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -50029,7 +50965,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -50127,6 +51063,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -50134,12 +51071,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = NULL; value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -50147,6 +51086,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = NULL; + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -50168,6 +51108,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D dim = NULL; assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -50175,13 +51116,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } if (IS_UNUSED != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -50328,13 +51271,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } if (IS_UNUSED != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -50481,13 +51426,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } if (IS_UNUSED != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -50585,6 +51532,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -50592,12 +51540,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = NULL; value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -50605,6 +51555,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = NULL; + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -50626,6 +51577,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D dim = NULL; assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -50633,13 +51585,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } if (IS_UNUSED != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { if (IS_CV == IS_UNUSED) { SAVE_OPLINE(); @@ -50706,7 +51660,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -50718,6 +51672,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_U arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -50753,7 +51708,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_U ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -50765,6 +51720,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_UNUSED_HANDLE arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -50779,10 +51735,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_UNUSED_HANDLE } ZVAL_REF(arg, Z_REF_P(varptr)); + ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -50794,6 +51751,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HAN arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -50815,6 +51773,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HAN } ZVAL_REF(arg, Z_REF_P(varptr)); + ZEND_VM_NEXT_OPCODE(); } @@ -50847,7 +51806,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_HAN ZEND_VM_NEXT_OPCODE(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -50859,6 +51818,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_C arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); if (UNEXPECTED(!arg)) { + HANDLE_EXCEPTION(); } } else { @@ -50880,6 +51840,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_C } ZVAL_REF(arg, Z_REF_P(varptr)); + ZEND_VM_NEXT_OPCODE(); } @@ -50912,7 +51873,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_C ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -50927,6 +51888,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_TMP_VAR) { @@ -50999,6 +51961,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -51008,7 +51971,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -51030,7 +51993,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HAND } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_CV_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_CV_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var = EX_VAR(opline->op1.var); @@ -51048,7 +52011,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_CV_SPEC_CV_UNUSED_HANDLE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varname; @@ -51071,6 +52034,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL name = zval_try_get_tmp_string(varname, &tmp_name); if (UNEXPECTED(!name)) { + HANDLE_EXCEPTION(); } } @@ -51082,11 +52046,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL zend_tmp_string_release(tmp_name); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_SET_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_SET_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -51108,7 +52073,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_S } } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_EMPTY_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_EMPTY_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -51130,7 +52095,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_CV_S } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -51154,6 +52119,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS zend_tmp_string_release(tmp_name); } + if (!value) { result = (opline->extended_value & ZEND_ISEMPTY); } else { @@ -51174,7 +52140,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr; @@ -51199,6 +52165,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_UNUSED_HAND ce = zend_fetch_class(NULL, opline->op2.num); if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } @@ -51216,10 +52183,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_UNUSED_HAND result = 0; } + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -51276,6 +52244,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); } while (0); + } } else { zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); @@ -51291,6 +52260,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + } else { ZVAL_COPY_VALUE(&generator->value, value); if (IS_CV == IS_CV) { @@ -51311,6 +52281,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z } ZVAL_COPY(&generator->key, key); + if (Z_TYPE(generator->key) == IS_LONG && Z_LVAL(generator->key) > generator->largest_used_integer_key ) { @@ -51338,7 +52309,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z ZEND_VM_RETURN(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CHECK_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1 = EX_VAR(opline->op1.var); @@ -51351,7 +52322,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CHECK_VAR_SPEC_CV_UNUSED_HANDL ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1 = EX_VAR(opline->op1.var); @@ -51384,7 +52355,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_MAKE_REF_SPEC_CV_UNUSED_HANDLE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -51436,10 +52407,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z ZVAL_LONG(EX_VAR(opline->result.var), count); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_COUNT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_array *ht = Z_ARRVAL_P(EX_VAR(opline->op1.var)); @@ -51454,7 +52426,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_ARRAY_SPEC_CV_UNUSED_HAN ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -51493,11 +52465,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_CLASS_SPEC_CV_UNUSED_HANDL break; } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1; @@ -51512,10 +52485,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GET_TYPE_SPEC_CV_UNUSED_HANDLE ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *varptr, *arg; @@ -51537,7 +52511,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51548,10 +52522,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OP div_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51562,10 +52538,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OP pow_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51638,11 +52616,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND concat_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51654,10 +52634,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE result = fast_is_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51669,10 +52651,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA result = fast_is_not_identical_function(op1, op2); + + ZEND_VM_SMART_BRANCH(result, 1); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51727,10 +52711,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51785,10 +52769,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_HANDL } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51843,10 +52827,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_HAND } } } - ZEND_VM_TAIL_CALL(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51901,10 +52885,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -51959,10 +52943,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_H } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -52017,10 +53001,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_ } } } - ZEND_VM_TAIL_CALL(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -52031,10 +53015,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(Z compare_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -52045,10 +53031,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZE boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -52136,12 +53124,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_HANDL FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -52238,10 +53228,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL } + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *var_ptr; @@ -52268,10 +53260,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OP_SPEC_CV_CV_HANDLER(Z } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -52332,10 +53326,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object; @@ -52394,10 +53390,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLE } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *dim, *value; @@ -52429,10 +53427,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -52441,13 +53441,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -52456,13 +53457,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLE container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -52472,10 +53474,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLE zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -52494,7 +53498,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_ } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -52503,13 +53507,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HAN container = EX_VAR(opline->op1.var); zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -52595,6 +53600,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER LOAD_OPLINE_EX(); + + ZEND_VM_ENTER_EX(); } /* Fall through to read_property for hooks. */ @@ -52674,10 +53681,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER fetch_obj_r_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -52692,13 +53701,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *result; @@ -52709,13 +53719,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLE result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -52833,10 +53844,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE fetch_obj_is_finish: + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { #if 0 USE_OPLINE @@ -52853,7 +53866,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_ } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container, *property, *result; @@ -52864,13 +53877,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HAN result = EX_VAR(opline->result.var); zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_VAR) { FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -52993,6 +54007,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -53013,18 +54028,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -53173,12 +54191,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -53327,12 +54347,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object, *value, tmp; @@ -53455,6 +54477,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); if (UNEXPECTED(!name)) { + UNDEF_RESULT(); goto exit_assign_obj; } @@ -53475,18 +54498,21 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); } + exit_assign_obj: if (garbage) { GC_DTOR_NO_REF(garbage); } + + /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -53584,6 +54610,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -53591,12 +54618,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = EX_VAR(opline->op2.var); value = RT_CONSTANT((opline+1), (opline+1)->op1); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -53604,6 +54633,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -53625,6 +54655,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -53632,13 +54663,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } if (IS_CV != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -53785,13 +54818,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } if (IS_CV != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -53938,13 +54973,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } if (IS_CV != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr, *orig_object_ptr; @@ -54042,6 +55079,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { zend_objects_store_del(obj); } @@ -54049,12 +55087,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); + UNDEF_RESULT(); } else { dim = EX_VAR(opline->op2.var); value = EX_VAR((opline+1)->op1.var); zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { if (Z_ISREF_P(orig_object_ptr) @@ -54062,6 +55102,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + UNDEF_RESULT(); } else { HashTable *ht = zend_new_array(8); @@ -54083,6 +55124,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); assign_dim_error: + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -54090,13 +55132,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } if (IS_CV != IS_UNUSED) { + } + /* assign_dim has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -54120,12 +55164,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *value; @@ -54149,12 +55194,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } + /* zend_assign_to_variable() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *variable_ptr; @@ -54189,10 +55235,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -54223,12 +55271,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D } + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *property, *container, *value_ptr; @@ -54260,11 +55310,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_D + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); } /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *op1, *op2; @@ -54386,10 +55439,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; @@ -54420,12 +55475,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA ZVAL_UNDEFINED_OP2(); if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); } } zend_throw_error(NULL, "Method name must be a string"); + + HANDLE_EXCEPTION(); } while (0); } @@ -54458,6 +55516,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA if (UNEXPECTED(EG(exception) != NULL)) { if (IS_CV != IS_CONST) { + } HANDLE_EXCEPTION(); } @@ -54468,6 +55527,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA zend_invalid_method_call(object, function_name); + + HANDLE_EXCEPTION(); } } while (0); @@ -54492,6 +55553,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); } + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { zend_objects_store_del(orig_obj); } @@ -54515,6 +55577,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA if (IS_CV != IS_CONST) { + } call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; @@ -54544,7 +55607,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *expr_ptr, new_expr; @@ -54559,6 +55622,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H ZVAL_MAKE_REF_EX(expr_ptr, 2); } + } else { expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); if (IS_CV == IS_TMP_VAR) { @@ -54631,6 +55695,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H zval_ptr_dtor_nogc(expr_ptr); } + } else { if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { zend_cannot_add_element(); @@ -54640,7 +55705,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *array; uint32_t size; @@ -54662,7 +55727,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER( } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -54750,10 +55815,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(Z } while (0); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *container; @@ -54791,348 +55858,56175 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z if (IS_CV != IS_CONST) { zend_tmp_string_release(tmp_name); } - } while (0); - - - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, IS_CV == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if (IS_CV & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = EX_VAR(opline->op1.var); + subject = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CV == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */ + /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */ + /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(!result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ +} + + +#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) +# undef ZEND_VM_TAIL_CALL +# undef ZEND_VM_CONTINUE +# undef ZEND_VM_RETURN + +# define ZEND_VM_TAIL_CALL(call) call; ZEND_VM_CONTINUE() +# define ZEND_VM_CONTINUE() HYBRID_NEXT() +# define ZEND_VM_RETURN() goto HYBRID_HALT_LABEL +#endif + +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + +# undef ZEND_VM_TAIL_CALL +# undef ZEND_VM_CONTINUE +# undef ZEND_VM_RETURN +# undef ZEND_VM_DISPATCH_TO_HELPER +# undef ZEND_VM_INTERRUPT + +# define ZEND_VM_TAIL_CALL(call) ZEND_MUSTTAIL return call +# define ZEND_VM_CONTINUE() ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) +# define ZEND_VM_RETURN() opline = &call_halt_op; ZEND_VM_CONTINUE() +# define ZEND_VM_DISPATCH_TO_HELPER(call) \ + do { \ + opline = call; \ + ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); \ + } while (0) +# define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE() +# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HALT_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS); +static zend_never_inline const zend_op *ZEND_OPCODE_HANDLER_CCONV zend_leave_helper_SPEC_TAILCALL(zend_execute_data *ex, const zend_op *opline); + +static const zend_op call_halt_op = { + .handler = ZEND_HALT_TAILCALL_HANDLER, +}; +static const zend_op call_leave_op = { + .handler = zend_leave_helper_SPEC_TAILCALL, +}; + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_add_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_sub_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_mul_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_mod_by_zero_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_mod_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_shift_left_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_shift_right_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_or_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_and_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_xor_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_not_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1); +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_this_not_in_object_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zend_throw_error(NULL, "Using $this when not in object context"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); +} + +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_undefined_function_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + + SAVE_OPLINE(); + function_name = RT_CONSTANT(opline, opline->op2); + zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(function_name)); + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_STATIC_PROP_OP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */ + + USE_OPLINE + zval *prop, *value; + zend_property_info *prop_info; + zend_reference *ref; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + UNDEF_RESULT(); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); + } + + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (UNEXPECTED(Z_ISREF_P(prop))) { + ref = Z_REF_P(prop); + prop = Z_REFVAL_P(prop); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + if (ZEND_TYPE_IS_SET(prop_info->type)) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, prop, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(prop, prop, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), prop); + } + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + /* assign_static_prop has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_STATIC_PROP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *prop; + zend_property_info *prop_info; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + zend_pre_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_STATIC_PROP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *prop; + zend_property_info *prop_info; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + zend_post_incdec_property_zval(prop, + ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_STATIC_PROP_R_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_STATIC_PROP_W_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_STATIC_PROP_RW_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + ZEND_VM_TAIL_CALL(ZEND_FETCH_STATIC_PROP_W_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_STATIC_PROP_R_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_STATIC_PROP_IS_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); +} + +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot use temporary expression in write context"); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); +} + +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot use [] for reading"); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *prop, *value; + zend_property_info *prop_info; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (ZEND_TYPE_IS_SET(prop_info->type)) { + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); + + + } else { + value = zend_assign_to_variable_ex(prop, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + /* assign_static_prop has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *prop, *value; + zend_property_info *prop_info; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (ZEND_TYPE_IS_SET(prop_info->type)) { + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } else { + value = zend_assign_to_variable_ex(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + /* assign_static_prop has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *prop, *value; + zend_property_info *prop_info; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (ZEND_TYPE_IS_SET(prop_info->type)) { + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } else { + value = zend_assign_to_variable_ex(prop, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + /* assign_static_prop has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *prop, *value; + zend_property_info *prop_info; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (ZEND_TYPE_IS_SET(prop_info->type)) { + value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC); + + + } else { + value = zend_assign_to_variable_ex(prop, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + /* assign_static_prop has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_STATIC_PROP_REF_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *prop, *value_ptr; + zend_property_info *prop_info; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address(&prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, BP_VAR_W); + + if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { + if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC))) { + prop = &EG(uninitialized_zval); + } + } else if (ZEND_TYPE_IS_SET(prop_info->type)) { + prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr, &garbage EXECUTE_DATA_CC); + } else { + zend_assign_to_variable_reference(prop, value_ptr, &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), prop); + } + + if (garbage) { + GC_DTOR(garbage); + } + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_leave_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_execute_data *old_execute_data; + uint32_t call_info = EX_CALL_INFO(); +#if ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL + /* zend_leave_helper may be called with opline=call_leave_op in TAILCALL VM */ + SAVE_OPLINE(); +#endif + + if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { + EG(current_execute_data) = EX(prev_execute_data); + i_free_compiled_variables(execute_data); + +#ifdef ZEND_PREFER_RELOAD + call_info = EX_CALL_INFO(); +#endif + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(execute_data->This)); + } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); + } + EG(vm_stack_top) = (zval*)execute_data; + execute_data = EX(prev_execute_data); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION_LEAVE(); + } + + LOAD_NEXT_OPLINE(); + ZEND_VM_LEAVE(); + } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) { + EG(current_execute_data) = EX(prev_execute_data); + i_free_compiled_variables(execute_data); + +#ifdef ZEND_PREFER_RELOAD + call_info = EX_CALL_INFO(); +#endif + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } + + /* Free extra args before releasing the closure, + * as that may free the op_array. */ + zend_vm_stack_free_extra_args_ex(call_info, execute_data); + + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(execute_data->This)); + } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); + } + + old_execute_data = execute_data; + execute_data = EX(prev_execute_data); + zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION_LEAVE(); + } + + LOAD_NEXT_OPLINE(); + ZEND_VM_LEAVE(); + } else if (EXPECTED((call_info & ZEND_CALL_TOP) == 0)) { + if (EX(func)->op_array.last_var > 0) { + zend_detach_symbol_table(execute_data); + call_info |= ZEND_CALL_NEEDS_REATTACH; + } + zend_destroy_static_vars(&EX(func)->op_array); + destroy_op_array(&EX(func)->op_array); + efree_size(EX(func), sizeof(zend_op_array)); + old_execute_data = execute_data; + execute_data = EG(current_execute_data) = EX(prev_execute_data); + zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + + if (call_info & ZEND_CALL_NEEDS_REATTACH) { + if (EX(func)->op_array.last_var > 0) { + zend_attach_symbol_table(execute_data); + } else { + ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_NEEDS_REATTACH); + } + } + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION_LEAVE(); + } + + LOAD_NEXT_OPLINE(); + ZEND_VM_LEAVE(); + } else { + if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) { + EG(current_execute_data) = EX(prev_execute_data); + i_free_compiled_variables(execute_data); +#ifdef ZEND_PREFER_RELOAD + call_info = EX_CALL_INFO(); +#endif + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS))) { + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + zend_vm_stack_free_extra_args_ex(call_info, execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } + } + if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); + } + ZEND_VM_RETURN(); + } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { + zend_array *symbol_table = EX(symbol_table); + + if (EX(func)->op_array.last_var > 0) { + zend_detach_symbol_table(execute_data); + call_info |= ZEND_CALL_NEEDS_REATTACH; + } + if (call_info & ZEND_CALL_NEEDS_REATTACH) { + old_execute_data = EX(prev_execute_data); + while (old_execute_data) { + if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) { + if (old_execute_data->symbol_table == symbol_table) { + if (old_execute_data->func->op_array.last_var > 0) { + zend_attach_symbol_table(old_execute_data); + } else { + ZEND_ADD_CALL_FLAG(old_execute_data, ZEND_CALL_NEEDS_REATTACH); + } + } + break; + } + old_execute_data = old_execute_data->prev_execute_data; + } + } + EG(current_execute_data) = EX(prev_execute_data); + ZEND_VM_RETURN(); + } + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_TAILCALL_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 = 0 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + + 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_VM_FCALL_INTERRUPT_CHECK(call); + + 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 (!0) { + i_zval_ptr_dtor(ret); + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + + ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICALL_SPEC_RETVAL_USED_TAILCALL_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 = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + + 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_VM_FCALL_INTERRUPT_CHECK(call); + + 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 (!1) { + i_zval_ptr_dtor(ret); + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + + ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICALL_SPEC_OBSERVER_TAILCALL_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_specialized(call, false); + 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); + ZEND_VM_FCALL_INTERRUPT_CHECK(call); + + 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_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + ret = NULL; + if (0) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_UCALL_SPEC_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + ret = NULL; + if (1) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_UCALL_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + ret = NULL; + if (RETURN_VALUE_USED(opline)) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin_specialized(execute_data, false); + + ZEND_VM_ENTER_EX(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_TAILCALL_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; + + const uint32_t no_discard = 0 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!0) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_by_name_end; + } + } + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (0) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } else { + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } + + 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 = 0 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + + 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_VM_FCALL_INTERRUPT_CHECK(call); + + EG(current_execute_data) = execute_data; + + goto fcall_by_name_end; + } + + if (0) { +fcall_by_name_end: + + 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 (!0) { + i_zval_ptr_dtor(ret); + } + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_TAILCALL_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; + + const uint32_t no_discard = 1 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!1) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_by_name_end; + } + } + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (1) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } else { + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } + + 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 = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + + 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_VM_FCALL_INTERRUPT_CHECK(call); + + EG(current_execute_data) = execute_data; + + goto fcall_by_name_end; + } + + if (0) { +fcall_by_name_end: + + 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 (!1) { + i_zval_ptr_dtor(ret); + } + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_TAILCALL_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; + + const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + if (!RETURN_VALUE_USED(opline)) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_by_name_end; + } + } + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (RETURN_VALUE_USED(opline)) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin_specialized(execute_data, false); + + ZEND_VM_ENTER_EX(); + } else { + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (1) { + ret = NULL; + } + + 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_specialized(call, false); + 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); + ZEND_VM_FCALL_INTERRUPT_CHECK(call); + + EG(current_execute_data) = execute_data; + + goto fcall_by_name_end; + } + + if (0) { +fcall_by_name_end: + + 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_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_TAILCALL_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; + + const uint32_t no_discard = 0 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } + if (UNEXPECTED(EG(exception) != NULL)) { + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); + } + UNDEF_RESULT(); + if (!0) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (0) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC); + + if (EXPECTED(zend_execute_ex == execute_ex)) { + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } else { + SAVE_OPLINE_EX(); + + + execute_data = EX(prev_execute_data); + LOAD_OPLINE(); + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } else { + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } + + 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 = 0 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(call, ret); + } + +#if ZEND_DEBUG + if (!EG(exception) && call->func && !(call->func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE)) { + 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_VM_FCALL_INTERRUPT_CHECK(call); + + EG(current_execute_data) = execute_data; + + goto fcall_end; + } + + if (0) { +fcall_end: + + zend_vm_stack_free_args(call); + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } + + if (!0) { + i_zval_ptr_dtor(ret); + } + } + + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(call->This)); + } + + zend_vm_stack_free_call_frame(call); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCALL_SPEC_RETVAL_USED_TAILCALL_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; + + const uint32_t no_discard = 1 ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } + if (UNEXPECTED(EG(exception) != NULL)) { + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); + } + UNDEF_RESULT(); + if (!1) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (1) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC); + + if (EXPECTED(zend_execute_ex == execute_ex)) { + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } else { + SAVE_OPLINE_EX(); + + + execute_data = EX(prev_execute_data); + LOAD_OPLINE(); + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } else { + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (0) { + ret = NULL; + } + + 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 = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(call, ret); + } + +#if ZEND_DEBUG + if (!EG(exception) && call->func && !(call->func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE)) { + 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_VM_FCALL_INTERRUPT_CHECK(call); + + EG(current_execute_data) = execute_data; + + goto fcall_end; + } + + if (0) { +fcall_end: + + zend_vm_stack_free_args(call); + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } + + if (!1) { + i_zval_ptr_dtor(ret); + } + } + + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(call->This)); + } + + zend_vm_stack_free_call_frame(call); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_FCALL_SPEC_OBSERVER_TAILCALL_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; + + const uint32_t no_discard = RETURN_VALUE_USED(opline) ? 0 : ZEND_ACC_NODISCARD; + + if (UNEXPECTED(fbc->common.fn_flags & (ZEND_ACC_DEPRECATED|no_discard))) { + if (fbc->common.fn_flags & ZEND_ACC_DEPRECATED) { + zend_deprecated_function(fbc); + } + if ((fbc->common.fn_flags & no_discard) && EG(exception) == NULL) { + zend_nodiscard_function(fbc); + } + if (UNEXPECTED(EG(exception) != NULL)) { + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func)); + } + UNDEF_RESULT(); + if (!RETURN_VALUE_USED(opline)) { + ret = &retval; + ZVAL_UNDEF(ret); + } + goto fcall_end; + } + } + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + ret = NULL; + if (RETURN_VALUE_USED(opline)) { + ret = EX_VAR(opline->result.var); + } + + call->prev_execute_data = execute_data; + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC); + + if (EXPECTED(zend_execute_ex == execute_ex)) { + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin_specialized(execute_data, false); + ZEND_VM_ENTER_EX(); + } else { + SAVE_OPLINE_EX(); + zend_observer_fcall_begin_specialized(execute_data, false); + execute_data = EX(prev_execute_data); + LOAD_OPLINE(); + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } else { + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + if (1) { + ret = NULL; + } + + 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_specialized(call, false); + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(call, ret); + } + +#if ZEND_DEBUG + if (!EG(exception) && call->func && !(call->func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE)) { + 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); + ZEND_VM_FCALL_INTERRUPT_CHECK(call); + + EG(current_execute_data) = execute_data; + + goto fcall_end; + } + + if (0) { +fcall_end: + + zend_vm_stack_free_args(call); + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } + + if (!RETURN_VALUE_USED(opline)) { + i_zval_ptr_dtor(ret); + } + } + + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(call->This)); + } + + zend_vm_stack_free_call_frame(call); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1); + ZEND_VM_CONTINUE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_CREATE_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *return_value = EX(return_value); + + if (EXPECTED(return_value)) { + USE_OPLINE + zend_generator *generator; + zend_execute_data *gen_execute_data; + uint32_t num_args, used_stack, call_info; + + SAVE_OPLINE(); + object_init_ex(return_value, zend_ce_generator); + + /* + * Normally the execute_data is allocated on the VM stack (because it does + * not actually do any allocation and thus is faster). For generators + * though this behavior would be suboptimal, because the (rather large) + * structure would have to be copied back and forth every time execution is + * suspended or resumed. That's why for generators the execution context + * is allocated on heap. + */ + num_args = EX_NUM_ARGS(); + if (EXPECTED(num_args <= EX(func)->op_array.num_args)) { + used_stack = (ZEND_CALL_FRAME_SLOT + EX(func)->op_array.last_var + EX(func)->op_array.T) * sizeof(zval); + gen_execute_data = (zend_execute_data*)emalloc(used_stack); + used_stack = (ZEND_CALL_FRAME_SLOT + EX(func)->op_array.last_var) * sizeof(zval); + } else { + used_stack = (ZEND_CALL_FRAME_SLOT + num_args + EX(func)->op_array.last_var + EX(func)->op_array.T - EX(func)->op_array.num_args) * sizeof(zval); + gen_execute_data = (zend_execute_data*)emalloc(used_stack); + } + memcpy(gen_execute_data, execute_data, used_stack); + + /* Save execution context in generator object. */ + generator = (zend_generator *) Z_OBJ_P(EX(return_value)); + generator->func = gen_execute_data->func; + generator->execute_data = gen_execute_data; + generator->frozen_call_stack = NULL; + generator->execute_fake.opline = NULL; + generator->execute_fake.func = NULL; + generator->execute_fake.prev_execute_data = NULL; + ZVAL_OBJ(&generator->execute_fake.This, (zend_object *) generator); + + gen_execute_data->opline = opline; + /* EX(return_value) keeps pointer to zend_object (not a real zval) */ + gen_execute_data->return_value = (zval*)generator; + call_info = Z_TYPE_INFO(EX(This)); + if ((call_info & Z_TYPE_MASK) == IS_OBJECT + && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS)) + /* Bug #72523 */ + || UNEXPECTED(zend_execute_ex != execute_ex))) { + ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS); + Z_ADDREF(gen_execute_data->This); + } + ZEND_ADD_CALL_FLAG_EX(call_info, (ZEND_CALL_TOP_FUNCTION | ZEND_CALL_ALLOCATED | ZEND_CALL_GENERATOR)); + Z_TYPE_INFO(gen_execute_data->This) = call_info; + gen_execute_data->prev_execute_data = NULL; + + call_info = EX_CALL_INFO(); + EG(current_execute_data) = EX(prev_execute_data); + if (EXPECTED(!(call_info & (ZEND_CALL_TOP|ZEND_CALL_ALLOCATED)))) { + EG(vm_stack_top) = (zval*)execute_data; + execute_data = EX(prev_execute_data); + LOAD_NEXT_OPLINE(); + ZEND_VM_LEAVE(); + } else if (EXPECTED(!(call_info & ZEND_CALL_TOP))) { + zend_execute_data *old_execute_data = execute_data; + execute_data = EX(prev_execute_data); + zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + LOAD_NEXT_OPLINE(); + ZEND_VM_LEAVE(); + } else { + ZEND_VM_RETURN(); + } + } else { + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); + } +} + +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t _arg_num, zval *_arg); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_UNPACK_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *args; + uint32_t arg_num; + + SAVE_OPLINE(); + args = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); + arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1; + +send_again: + if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(args); + zval *arg, *top; + zend_string *name; + bool have_named_params = 0; + + zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht)); + + // TODO: Speed this up using a flag that specifies whether there are any ref parameters. + if ((opline->op1_type & (IS_VAR|IS_CV)) && Z_REFCOUNT_P(args) > 1) { + uint32_t tmp_arg_num = arg_num; + bool separate = 0; + + /* check if any of arguments are going to be passed by reference */ + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { + if (UNEXPECTED(name)) { + void *cache_slot[2] = {NULL, NULL}; + tmp_arg_num = zend_get_arg_offset_by_name( + EX(call)->func, name, cache_slot) + 1; + } + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, tmp_arg_num)) { + separate = 1; + break; + } + tmp_arg_num++; + } ZEND_HASH_FOREACH_END(); + if (separate) { + SEPARATE_ARRAY(args); + ht = Z_ARRVAL_P(args); + } + } + + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { + if (UNEXPECTED(name)) { + void *cache_slot[2] = {NULL, NULL}; + have_named_params = 1; + top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot); + if (UNEXPECTED(!top)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } else { + if (have_named_params) { + zend_throw_error(NULL, + "Cannot use positional argument after named argument during unpacking"); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + + top = ZEND_CALL_ARG(EX(call), arg_num); + ZEND_CALL_NUM_ARGS(EX(call))++; + } + + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + if (Z_ISREF_P(arg)) { + Z_ADDREF_P(arg); + ZVAL_REF(top, Z_REF_P(arg)); + } else if (opline->op1_type & (IS_VAR|IS_CV)) { + /* array is already separated above */ + ZVAL_MAKE_REF_EX(arg, 2); + ZVAL_REF(top, Z_REF_P(arg)); + } else { + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(top, arg); + } + } else { + ZVAL_COPY_DEREF(top, arg); + } + + arg_num++; + } ZEND_HASH_FOREACH_END(); + + } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(args); + zend_object_iterator *iter; + bool have_named_params = 0; + + if (!ce || !ce->get_iterator) { + zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(args)); + } else { + + iter = ce->get_iterator(ce, args, 0); + if (UNEXPECTED(!iter)) { + FREE_OP(opline->op1_type, opline->op1.var); + if (!EG(exception)) { + zend_throw_exception_ex( + NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name) + ); + } + HANDLE_EXCEPTION(); + } + + const zend_object_iterator_funcs *funcs = iter->funcs; + if (funcs->rewind) { + funcs->rewind(iter); + } + + for (; funcs->valid(iter) == SUCCESS; ++arg_num) { + zval *arg, *top; + + if (UNEXPECTED(EG(exception) != NULL)) { + break; + } + + arg = funcs->get_current_data(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + break; + } + + zend_string *name = NULL; + if (funcs->get_current_key) { + zval key; + funcs->get_current_key(iter, &key); + if (UNEXPECTED(EG(exception) != NULL)) { + break; + } + + if (UNEXPECTED(Z_TYPE(key) != IS_LONG)) { + if (UNEXPECTED(Z_TYPE(key) != IS_STRING)) { + zend_throw_error(NULL, + "Keys must be of type int|string during argument unpacking"); + zval_ptr_dtor(&key); + break; + } + + name = Z_STR_P(&key); + + zend_ulong tmp; + if (ZEND_HANDLE_NUMERIC(name, tmp)) { + name = NULL; + } + } + } + + if (UNEXPECTED(name)) { + void *cache_slot[2] = {NULL, NULL}; + have_named_params = 1; + top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot); + if (UNEXPECTED(!top)) { + zend_string_release(name); + break; + } + + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + zend_error( + E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" + " by unpacking a Traversable, passing by-value instead", arg_num, + EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "", + EX(call)->func->common.scope ? "::" : "", + ZSTR_VAL(EX(call)->func->common.function_name) + ); + ZVAL_NEW_REF(top, arg); + } else { + ZVAL_COPY_VALUE(top, arg); + } + + zend_string_release(name); + } else { + if (have_named_params) { + zend_throw_error(NULL, + "Cannot use positional argument after named argument during unpacking"); + break; + } + + zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1); + top = ZEND_CALL_ARG(EX(call), arg_num); + ZVAL_DEREF(arg); + Z_TRY_ADDREF_P(arg); + + if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + zend_error( + E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()" + " by unpacking a Traversable, passing by-value instead", arg_num, + EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "", + EX(call)->func->common.scope ? "::" : "", + ZSTR_VAL(EX(call)->func->common.function_name) + ); + ZVAL_NEW_REF(top, arg); + } else { + ZVAL_COPY_VALUE(top, arg); + } + + ZEND_CALL_NUM_ARGS(EX(call))++; + } + + funcs->move_forward(iter); + } + + zend_iterator_dtor(iter); + } + } else if (EXPECTED(Z_ISREF_P(args))) { + args = Z_REFVAL_P(args); + goto send_again; + } else { + if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(args)); + } + + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_ARRAY_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *args; + + SAVE_OPLINE(); + args = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + + if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) { + if ((opline->op1_type & (IS_VAR|IS_CV)) && Z_ISREF_P(args)) { + args = Z_REFVAL_P(args); + if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) { + goto send_array; + } + } + zend_type_error("call_user_func_array(): Argument #2 ($args) must be of type array, %s given", zend_zval_value_name(args)); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } else { + uint32_t arg_num; + HashTable *ht; + zval *arg, *param; + +send_array: + ht = Z_ARRVAL_P(args); + if (opline->op2_type != IS_UNUSED) { + /* We don't need to handle named params in this case, + * because array_slice() is called with $preserve_keys == false. */ + zval *op2 = get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R); + uint32_t skip = opline->extended_value; + uint32_t count = zend_hash_num_elements(ht); + zend_long len; + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + len = Z_LVAL_P(op2); + } else if (Z_TYPE_P(op2) == IS_NULL) { + len = count - skip; + } else if (EX_USES_STRICT_TYPES() + || !zend_parse_arg_long_weak(op2, &len, /* arg_num */ 3)) { + zend_type_error( + "array_slice(): Argument #3 ($length) must be of type ?int, %s given", + zend_zval_value_name(op2)); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + + if (len < 0) { + len += (zend_long)(count - skip); + } + if (skip < count && len > 0) { + if (len > (zend_long)(count - skip)) { + len = (zend_long)(count - skip); + } + zend_vm_stack_extend_call_frame(&EX(call), 0, len); + arg_num = 1; + param = ZEND_CALL_ARG(EX(call), 1); + ZEND_HASH_FOREACH_VAL(ht, arg) { + bool must_wrap = 0; + if (skip > 0) { + skip--; + continue; + } else if ((zend_long)(arg_num - 1) >= len) { + break; + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + if (UNEXPECTED(!Z_ISREF_P(arg))) { + if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + /* By-value send is not allowed -- emit a warning, + * but still perform the call. */ + zend_param_must_be_ref(EX(call)->func, arg_num); + must_wrap = 1; + } + } + } else { + if (Z_ISREF_P(arg) && + !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + } + if (EXPECTED(!must_wrap)) { + ZVAL_COPY(param, arg); + } else { + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(param, arg); + } + ZEND_CALL_NUM_ARGS(EX(call))++; + arg_num++; + param++; + } ZEND_HASH_FOREACH_END(); + } + FREE_OP(opline->op2_type, opline->op2.var); + } else { + zend_string *name; + bool have_named_params; + zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht)); + arg_num = 1; + param = ZEND_CALL_ARG(EX(call), 1); + have_named_params = 0; + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) { + if (name) { + void *cache_slot[2] = {NULL, NULL}; + have_named_params = 1; + param = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot); + if (!param) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } else if (have_named_params) { + zend_throw_error(NULL, + "Cannot use positional argument after named argument"); + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + + bool must_wrap = 0; + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + if (UNEXPECTED(!Z_ISREF_P(arg))) { + if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + /* By-value send is not allowed -- emit a warning, + * but still perform the call. */ + zend_param_must_be_ref(EX(call)->func, arg_num); + must_wrap = 1; + } + } + } else { + if (Z_ISREF_P(arg) && + !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + /* don't separate references for __call */ + arg = Z_REFVAL_P(arg); + } + } + + if (EXPECTED(!must_wrap)) { + ZVAL_COPY(param, arg); + } else { + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(param, arg); + } + if (!name) { + ZEND_CALL_NUM_ARGS(EX(call))++; + arg_num++; + param++; + } + } ZEND_HASH_FOREACH_END(); + } + } + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_missing_arg_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + + zend_missing_arg_error(execute_data); + HANDLE_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_verify_recv_arg_type_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1); +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RECV_NOTYPE_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num = opline->op1.num; + + if (UNEXPECTED(arg_num > EX_NUM_ARGS())) { + ZEND_VM_TAIL_CALL(zend_missing_arg_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_case_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_UNPACK_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + HashTable *result_ht; + + SAVE_OPLINE(); + op1 = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + result_ht = Z_ARRVAL_P(EX_VAR(opline->result.var)); + +add_unpack_again: + if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) { + HashTable *ht = Z_ARRVAL_P(op1); + zval *val; + + if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) { + /* zend_hash_extend() skips initialization when the number of elements is 0, + * but the code below expects that result_ht is initialized as packed. + * We can just skip the work in that case. */ + if (result_ht->nNumUsed + zend_hash_num_elements(ht) > 0) { + zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1); + ZEND_HASH_FILL_PACKED(result_ht) { + ZEND_HASH_PACKED_FOREACH_VAL(ht, val) { + if (UNEXPECTED(Z_ISREF_P(val)) && + UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { + val = Z_REFVAL_P(val); + } + Z_TRY_ADDREF_P(val); + ZEND_HASH_FILL_ADD(val); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FILL_END(); + } + } else { + zend_string *key; + + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) { + if (UNEXPECTED(Z_ISREF_P(val)) && + UNEXPECTED(Z_REFCOUNT_P(val) == 1)) { + val = Z_REFVAL_P(val); + } + Z_TRY_ADDREF_P(val); + if (key) { + zend_hash_update(result_ht, key, val); + } else { + if (!zend_hash_next_index_insert(result_ht, val)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(val); + break; + } + } + } ZEND_HASH_FOREACH_END(); + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_OBJECT)) { + zend_class_entry *ce = Z_OBJCE_P(op1); + zend_object_iterator *iter; + + if (!ce || !ce->get_iterator) { + zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(op1)); + } else { + iter = ce->get_iterator(ce, op1, 0); + if (UNEXPECTED(!iter)) { + FREE_OP(opline->op1_type, opline->op1.var); + if (!EG(exception)) { + zend_throw_exception_ex( + NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name) + ); + } + HANDLE_EXCEPTION(); + } + + const zend_object_iterator_funcs *funcs = iter->funcs; + if (funcs->rewind) { + funcs->rewind(iter); + } + + for (; funcs->valid(iter) == SUCCESS; ) { + zval *val; + + if (UNEXPECTED(EG(exception) != NULL)) { + break; + } + + val = funcs->get_current_data(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + break; + } + + zval key; + if (funcs->get_current_key) { + funcs->get_current_key(iter, &key); + if (UNEXPECTED(EG(exception) != NULL)) { + break; + } + + if (UNEXPECTED(Z_TYPE(key) != IS_LONG && Z_TYPE(key) != IS_STRING)) { + zend_throw_error(NULL, + "Keys must be of type int|string during array unpacking"); + zval_ptr_dtor(&key); + break; + } + } else { + ZVAL_UNDEF(&key); + } + + ZVAL_DEREF(val); + Z_TRY_ADDREF_P(val); + + zend_ulong num_key; + if (Z_TYPE(key) == IS_STRING && !ZEND_HANDLE_NUMERIC(Z_STR(key), num_key)) { + zend_hash_update(result_ht, Z_STR(key), val); + zval_ptr_dtor_str(&key); + } else { + zval_ptr_dtor(&key); + if (!zend_hash_next_index_insert(result_ht, val)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(val); + break; + } + } + + funcs->move_forward(iter); + if (UNEXPECTED(EG(exception))) { + break; + } + } + + zend_iterator_dtor(iter); + } + } else if (EXPECTED(Z_ISREF_P(op1))) { + op1 = Z_REFVAL_P(op1); + goto add_unpack_again; + } else { + zend_throw_error(NULL, "Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(op1)); + } + + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_STATIC_PROP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varname; + zend_string *name, *tmp_name = NULL; + zend_class_entry *ce; + + SAVE_OPLINE(); + + if (opline->op2_type == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + /*CACHE_PTR(opline->extended_value, ce);*/ + } + } else if (opline->op2_type == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + + varname = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); + if (opline->op1_type == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + } else { + if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + } + + zend_std_unset_static_property(ce, name); + + zend_tmp_string_release(tmp_name); + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_fe_fetch_object_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array; + zval *value; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + Bucket *p; + zend_object_iterator *iter; + + array = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + + ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT); + if ((iter = zend_iterator_unwrap(array)) == NULL) { + /* plain object */ + + fe_ht = Z_OBJPROP_P(array); + pos = zend_hash_iterator_pos(Z_FE_ITER_P(array), fe_ht); + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_r_exit; + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + if (UNEXPECTED(value_type == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF) + && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) { + break; + } + } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0) + || !p->key + || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) { + break; + } + } + p++; + } + EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos; + if (RETURN_VALUE_USED(opline)) { + if (UNEXPECTED(!p->key)) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else if (ZSTR_VAL(p->key)[0]) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + const char *class_name, *prop_name; + size_t prop_name_len; + zend_unmangle_property_name_ex( + p->key, &class_name, &prop_name, &prop_name_len); + ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len); + } + } + } else { + const zend_object_iterator_funcs *funcs = iter->funcs; + if (EXPECTED(++iter->index > 0)) { + /* This could cause an endless loop if index becomes zero again. + * In case that ever happens we need an additional flag. */ + funcs->move_forward(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(funcs->valid(iter) == FAILURE)) { + /* reached end of iteration */ + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } +fe_fetch_r_exit: + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + } + value = funcs->get_current_data(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (!value) { + /* failure in get_current_data */ + goto fe_fetch_r_exit; + } + if (RETURN_VALUE_USED(opline)) { + if (funcs->get_current_key) { + funcs->get_current_key(iter, EX_VAR(opline->result.var)); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } else { + ZVAL_LONG(EX_VAR(opline->result.var), iter->index); + } + } + value_type = Z_TYPE_INFO_P(value); + } + + if (EXPECTED(opline->op2_type == IS_CV)) { + zval *variable_ptr = EX_VAR(opline->op2.var); + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zval *res = EX_VAR(opline->op2.var); + zend_refcounted *gc = Z_COUNTED_P(value); + + ZVAL_COPY_VALUE_EX(res, value, gc, value_type); + if (Z_TYPE_INFO_REFCOUNTED(value_type)) { + GC_ADDREF(gc); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + bool result; + + SAVE_OPLINE(); + + value = zend_fetch_static_property_address(NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC); + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + } else { + result = value == NULL || !i_zend_is_true(value); + } + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BEGIN_SILENCE_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting)); + + if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) { + do { + /* Do not silence fatal errors */ + EG(error_reporting) &= E_FATAL_ERRORS; + if (!EG(error_reporting_ini_entry)) { + zval *zv = zend_hash_find_known_hash(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING)); + if (zv) { + EG(error_reporting_ini_entry) = (zend_ini_entry *)Z_PTR_P(zv); + } else { + break; + } + } + if (!EG(error_reporting_ini_entry)->modified) { + if (!EG(modified_ini_directives)) { + ALLOC_HASHTABLE(EG(modified_ini_directives)); + zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0); + } + if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), EG(error_reporting_ini_entry)) != NULL)) { + EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value; + EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable; + EG(error_reporting_ini_entry)->modified = 1; + } + } + } while (0); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_EXT_STMT_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (!EG(no_extensions)) { + SAVE_OPLINE(); + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, execute_data); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_EXT_FCALL_BEGIN_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (!EG(no_extensions)) { + SAVE_OPLINE(); + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, execute_data); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_EXT_FCALL_END_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (!EG(no_extensions)) { + SAVE_OPLINE(); + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, execute_data); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_ANON_CLASS_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *zv; + zend_class_entry *ce; + USE_OPLINE + + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1)); + zv = zend_hash_find_known_hash(EG(class_table), rtd_key); + ZEND_ASSERT(zv != NULL); + ce = Z_CE_P(zv); + if (!(ce->ce_flags & ZEND_ACC_LINKED)) { + SAVE_OPLINE(); + ce = zend_do_link_class(ce, (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL, rtd_key); + if (EG(exception)) { + HANDLE_EXCEPTION(); + } + } + CACHE_PTR(opline->extended_value, ce); + } + Z_CE_P(EX_VAR(opline->result.var)) = ce; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_FUNCTION_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_function *func; + USE_OPLINE + + SAVE_OPLINE(); + func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num]; + do_bind_function(func, RT_CONSTANT(opline, opline->op1)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_TICKS_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if ((uint32_t)++EG(ticks_count) >= opline->extended_value) { + 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(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_EXT_NOP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NOP_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + ZEND_VM_NEXT_OPCODE(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t try_catch_offset, uint32_t op_num); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HANDLE_EXCEPTION_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + const zend_op *throw_op = EG(opline_before_exception); + + /* Exception was thrown before executing any op */ + if (UNEXPECTED(!throw_op)) { + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX -1, 0)); + } + + uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes; + int i, current_try_catch_offset = -1; + + if ((throw_op->opcode == ZEND_FREE || throw_op->opcode == ZEND_FE_FREE) + && throw_op->extended_value & ZEND_FREE_ON_RETURN) { + /* exceptions thrown because of loop var destruction on return/break/... + * are logically thrown at the end of the foreach loop, so adjust the + * throw_op_num. + */ + const zend_live_range *range = find_live_range( + &EX(func)->op_array, throw_op_num, throw_op->op1.var); + /* free op1 of the corresponding RETURN */ + for (i = throw_op_num; i < range->end; i++) { + if (EX(func)->op_array.opcodes[i].opcode == ZEND_FREE + || EX(func)->op_array.opcodes[i].opcode == ZEND_FE_FREE) { + /* pass */ + } else { + if (EX(func)->op_array.opcodes[i].opcode == ZEND_RETURN + && (EX(func)->op_array.opcodes[i].op1_type & (IS_VAR|IS_TMP_VAR))) { + zval_ptr_dtor(EX_VAR(EX(func)->op_array.opcodes[i].op1.var)); + } + break; + } + } + throw_op_num = range->end; + } + + /* Find the innermost try/catch/finally the exception was thrown in */ + for (i = 0; i < EX(func)->op_array.last_try_catch; i++) { + zend_try_catch_element *try_catch = &EX(func)->op_array.try_catch_array[i]; + if (try_catch->try_op > throw_op_num) { + /* further blocks will not be relevant... */ + break; + } + if (throw_op_num < try_catch->catch_op || throw_op_num < try_catch->finally_end) { + current_try_catch_offset = i; + } + } + + cleanup_unfinished_calls(execute_data, throw_op_num); + + if (throw_op->result_type & (IS_VAR | IS_TMP_VAR)) { + switch (throw_op->opcode) { + case ZEND_ADD_ARRAY_ELEMENT: + case ZEND_ADD_ARRAY_UNPACK: + case ZEND_ROPE_INIT: + case ZEND_ROPE_ADD: + break; /* exception while building structures, live range handling will free those */ + + case ZEND_FETCH_CLASS: + case ZEND_DECLARE_ANON_CLASS: + break; /* return value is zend_class_entry pointer */ + + default: + /* smart branch opcodes may not initialize result */ + if (!zend_is_smart_branch(throw_op)) { + zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var)); + } + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, throw_op_num)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_USER_OPCODE_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + int ret; + + SAVE_OPLINE(); + ret = zend_user_opcode_handlers[opline->opcode](execute_data); + opline = EX(opline); + + switch (ret) { + case ZEND_USER_OPCODE_CONTINUE: + ZEND_VM_CONTINUE(); + case ZEND_USER_OPCODE_RETURN: + if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + EG(current_execute_data) = EX(prev_execute_data); + zend_generator_close(generator, 1); + ZEND_VM_RETURN(); + } else { + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); + } + case ZEND_USER_OPCODE_ENTER: + ZEND_VM_ENTER(); + case ZEND_USER_OPCODE_LEAVE: + ZEND_VM_LEAVE(); + case ZEND_USER_OPCODE_DISPATCH: + ZEND_VM_DISPATCH(opline->opcode, opline); + default: + ZEND_VM_DISPATCH((uint8_t)(ret & 0xff), opline); + } +} + +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot yield from finally in a force-closed generator"); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP(opline->op1_type, opline->op1.var); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DISCARD_EXCEPTION_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *fast_call = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + + /* cleanup incomplete RETURN statement */ + if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1 + && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) { + zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); + + zval_ptr_dtor(return_value); + } + + /* cleanup delayed exception */ + if (Z_OBJ_P(fast_call) != NULL) { + /* discard the previously thrown exception */ + OBJ_RELEASE(Z_OBJ_P(fast_call)); + Z_OBJ_P(fast_call) = NULL; + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CALL_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *fast_call = EX_VAR(opline->result.var); + + Z_OBJ_P(fast_call) = NULL; + /* set return address */ + Z_OPLINE_NUM_P(fast_call) = opline - EX(func)->op_array.opcodes; + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_RET_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *fast_call = EX_VAR(opline->op1.var); + uint32_t current_try_catch_offset, current_op_num; + + if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1) { + const zend_op *fast_ret = EX(func)->op_array.opcodes + Z_OPLINE_NUM_P(fast_call); + + ZEND_VM_JMP_EX(fast_ret + 1, 0); + } + + /* special case for unhandled exceptions */ + EG(exception) = Z_OBJ_P(fast_call); + Z_OBJ_P(fast_call) = NULL; + current_try_catch_offset = opline->op2.num; + current_op_num = opline - EX(func)->op_array.opcodes; + ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX current_try_catch_offset, current_op_num)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSERT_CHECK_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EG(assertions) <= 0) { + zend_op *target = OP_JMP_ADDR(opline, opline->op2); + if (RETURN_VALUE_USED(opline)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + ZEND_VM_JMP_EX(target, 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALL_TRAMPOLINE_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_array *args = NULL; + zend_function *fbc = EX(func); + zval *ret = EX(return_value); + uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS); + uint32_t num_args = EX_NUM_ARGS(); + zend_execute_data *call; + + SAVE_OPLINE(); + + if (num_args) { + zval *p = ZEND_CALL_ARG(execute_data, 1); + zval *end = p + num_args; + + args = zend_new_array(num_args); + zend_hash_real_init_packed(args); + ZEND_HASH_FILL_PACKED(args) { + do { + ZEND_HASH_FILL_ADD(p); + p++; + } while (p != end); + } ZEND_HASH_FILL_END(); + } + + call = execute_data; + execute_data = EG(current_execute_data) = EX(prev_execute_data); + + call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_CALL_NUM_ARGS(call) = 2; + + ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); + + zval *call_args = ZEND_CALL_ARG(call, 2); + if (args) { + ZVAL_ARR(call_args, args); + } else { + ZVAL_EMPTY_ARRAY(call_args); + } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + if (zend_hash_num_elements(Z_ARRVAL_P(call_args)) == 0) { + GC_ADDREF(call->extra_named_params); + ZVAL_ARR(call_args, call->extra_named_params); + } else { + SEPARATE_ARRAY(call_args); + zend_hash_copy(Z_ARRVAL_P(call_args), call->extra_named_params, zval_add_ref); + } + } + zend_free_trampoline(fbc); + fbc = call->func; + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + if (EXPECTED(zend_execute_ex == execute_ex)) { + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } else { + SAVE_OPLINE_EX(); + + + execute_data = EX(prev_execute_data); + if (execute_data) { + LOAD_OPLINE(); + } + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } else { + zval retval; + + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + + EG(current_execute_data) = call; + +#if ZEND_DEBUG + bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + + if (ret == NULL) { + ret = &retval; + } + + ZVAL_NULL(ret); + + + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(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 + + + EG(current_execute_data) = call->prev_execute_data; + + zend_vm_stack_free_args(call); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } + if (ret == &retval) { + zval_ptr_dtor(ret); + } + } + + execute_data = EG(current_execute_data); + + if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { + ZEND_VM_RETURN(); + } + + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + zend_object *object = Z_OBJ(call->This); + OBJ_RELEASE(object); + } + zend_vm_stack_free_call_frame(call); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION_LEAVE(); + } + + LOAD_OPLINE(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_array *args = NULL; + zend_function *fbc = EX(func); + zval *ret = EX(return_value); + uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS); + uint32_t num_args = EX_NUM_ARGS(); + zend_execute_data *call; + + SAVE_OPLINE(); + + if (num_args) { + zval *p = ZEND_CALL_ARG(execute_data, 1); + zval *end = p + num_args; + + args = zend_new_array(num_args); + zend_hash_real_init_packed(args); + ZEND_HASH_FILL_PACKED(args) { + do { + ZEND_HASH_FILL_ADD(p); + p++; + } while (p != end); + } ZEND_HASH_FILL_END(); + } + + call = execute_data; + execute_data = EG(current_execute_data) = EX(prev_execute_data); + + call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call; + ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + ZEND_CALL_NUM_ARGS(call) = 2; + + ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); + + zval *call_args = ZEND_CALL_ARG(call, 2); + if (args) { + ZVAL_ARR(call_args, args); + } else { + ZVAL_EMPTY_ARRAY(call_args); + } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + if (zend_hash_num_elements(Z_ARRVAL_P(call_args)) == 0) { + GC_ADDREF(call->extra_named_params); + ZVAL_ARR(call_args, call->extra_named_params); + } else { + SEPARATE_ARRAY(call_args); + zend_hash_copy(Z_ARRVAL_P(call_args), call->extra_named_params, zval_add_ref); + } + } + zend_free_trampoline(fbc); + fbc = call->func; + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + execute_data = call; + i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); + if (EXPECTED(zend_execute_ex == execute_ex)) { + LOAD_OPLINE_EX(); + SAVE_OPLINE(); + zend_observer_fcall_begin_specialized(execute_data, false); + ZEND_VM_ENTER_EX(); + } else { + SAVE_OPLINE_EX(); + zend_observer_fcall_begin_specialized(execute_data, false); + execute_data = EX(prev_execute_data); + if (execute_data) { + LOAD_OPLINE(); + } + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } else { + zval retval; + + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + + EG(current_execute_data) = call; + +#if ZEND_DEBUG + bool should_throw = zend_internal_call_should_throw(fbc, call); +#endif + + if (ret == NULL) { + ret = &retval; + } + + ZVAL_NULL(ret); + zend_observer_fcall_begin_specialized(call, false); + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(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) = call->prev_execute_data; + + zend_vm_stack_free_args(call); + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(call->extra_named_params); + } + if (ret == &retval) { + zval_ptr_dtor(ret); + } + } + + execute_data = EG(current_execute_data); + + if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) { + ZEND_VM_RETURN(); + } + + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + zend_object *object = Z_OBJ(call->This); + OBJ_RELEASE(object); + } + zend_vm_stack_free_call_frame(call); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION_LEAVE(); + } + + LOAD_OPLINE(); + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_2_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + zval *arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + zval *arg2 = get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + +#if 0 || 0 + if (0 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline); + function(result, arg1, arg2); + } + + FREE_OP(opline->op1_type, opline->op1.var); + /* Set OP1 to UNDEF in case FREE_OP(opline->op2_type, opline->op2.var) throws. */ + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_2_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + zval *arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + zval *arg2 = get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + +#if 0 || 1 + if (1 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline); + function(result, arg1, arg2); + } + + FREE_OP(opline->op1_type, opline->op1.var); + /* Set OP1 to UNDEF in case FREE_OP(opline->op2_type, opline->op2.var) throws. */ + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_3_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + zval *arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + zval *arg2 = get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R); + zval *arg3 = get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); + } + +#if 0 || 0 + if (0 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline); + function(result, arg1, arg2, arg3); + } + + FREE_OP(opline->op1_type, opline->op1.var); + /* Set to UNDEF in case FREE_OP(opline->op2_type, opline->op2.var) throws. */ + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP(opline->op2_type, opline->op2.var); + if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op2.var)); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + zval *arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + zval *arg2 = get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R); + zval *arg3 = get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + FREE_OP(opline->op2_type, opline->op2.var); + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); + } + +#if 0 || 1 + if (1 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline); + function(result, arg1, arg2, arg3); + } + + FREE_OP(opline->op1_type, opline->op1.var); + /* Set to UNDEF in case FREE_OP(opline->op2_type, opline->op2.var) throws. */ + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op1.var)); + } + FREE_OP(opline->op2_type, opline->op2.var); + if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->op2.var)); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_FORWARD_SPEC_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + OPLINE = OP_JMP_ADDR(opline, opline->op1); + ZEND_VM_CONTINUE(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_atomic_bool_store_ex(&EG(vm_interrupt), false); + SAVE_OPLINE(); + if (zend_atomic_bool_load_ex(&EG(timed_out))) { + zend_timeout(); + } else if (zend_interrupt_function) { + zend_interrupt_function(execute_data); + if (EG(exception)) { + /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ + const zend_op *throw_op = EG(opline_before_exception); + + if (throw_op + && throw_op->result_type & (IS_TMP_VAR|IS_VAR) + && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT + && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK + && throw_op->opcode != ZEND_ROPE_INIT + && throw_op->opcode != ZEND_ROPE_ADD) { + ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); + + } + } + ZEND_VM_ENTER(); + } + ZEND_VM_CONTINUE(); +} +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_function *fbc; + zval *function_name, *func; + zend_execute_data *call; + + fbc = CACHED_PTR(opline->result.num); + if (UNEXPECTED(fbc == NULL)) { + function_name = (zval*)RT_CONSTANT(opline, opline->op2); + func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1)); + if (UNEXPECTED(func == NULL)) { + ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + fbc = Z_FUNC_P(func); + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + CACHE_PTR(opline->result.num, fbc); + } + call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, NULL); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_execute_data *call; + + SAVE_OPLINE(); + function_name = RT_CONSTANT(opline, opline->op2); + +try_function_name: + if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); + } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { + call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { + function_name = Z_REFVAL_P(function_name); + goto try_function_name; + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + function_name = ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Value of type %s is not callable", + zend_zval_type_name(function_name)); + call = NULL; + } + + if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { + + + if (UNEXPECTED(EG(exception))) { + if (call) { + if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { + zend_string_release_ex(call->func->common.function_name, 0); + zend_free_trampoline(call->func); + } + zend_vm_stack_free_call_frame(call); + } + HANDLE_EXCEPTION(); + } + } else if (!call) { + HANDLE_EXCEPTION(); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *func_name; + zval *func; + zend_function *fbc; + zend_execute_data *call; + + fbc = CACHED_PTR(opline->result.num); + if (UNEXPECTED(fbc == NULL)) { + func_name = (zval *)RT_CONSTANT(opline, opline->op2); + func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1)); + if (func == NULL) { + func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2)); + if (UNEXPECTED(func == NULL)) { + ZEND_VM_TAIL_CALL(zend_undefined_function_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + } + fbc = Z_FUNC_P(func); + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + CACHE_PTR(opline->result.num, fbc); + } + + call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, NULL); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_FCALL_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *fname; + zval *func; + zend_function *fbc; + zend_execute_data *call; + + fbc = CACHED_PTR(opline->result.num); + if (UNEXPECTED(fbc == NULL)) { + fname = (zval*)RT_CONSTANT(opline, opline->op2); + func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname)); + ZEND_ASSERT(func != NULL && "Function existence must be checked at compile time"); + fbc = Z_FUNC_P(func); + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + CACHE_PTR(opline->result.num, fbc); + } + + call = _zend_vm_stack_push_call_frame_ex( + opline->op1.num, ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, NULL); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_FCALL_OFFSET_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_function *fbc; + zend_execute_data *call; + fbc = CACHED_PTR(opline->result.num); + if (UNEXPECTED(fbc == NULL)) { + fbc = Z_PTR(EG(function_table)->arData[Z_EXTRA_P(RT_CONSTANT(opline, opline->op2))].val); + CACHE_PTR(opline->result.num, fbc); + } + call = _zend_vm_stack_push_call_frame_ex( + opline->op1.num, ZEND_CALL_NESTED_FUNCTION, + fbc, opline->extended_value, NULL); + call->prev_execute_data = EX(call); + EX(call) = call; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RECV_INIT_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num; + zval *param; + + ZEND_VM_REPEATABLE_OPCODE + + arg_num = opline->op1.num; + param = EX_VAR(opline->result.var); + if (arg_num > EX_NUM_ARGS()) { + zval *default_value = RT_CONSTANT(opline, opline->op2); + + if (Z_OPT_TYPE_P(default_value) == IS_CONSTANT_AST) { + zval *cache_val = (zval*)CACHE_ADDR(Z_CACHE_SLOT_P(default_value)); + + /* we keep in cache only not refcounted values */ + if (Z_TYPE_P(cache_val) != IS_UNDEF) { + ZVAL_COPY_VALUE(param, cache_val); + } else { + SAVE_OPLINE(); + ZVAL_COPY(param, default_value); + zend_ast_evaluate_ctx ctx = {0}; + if (UNEXPECTED(zval_update_constant_with_ctx(param, EX(func)->op_array.scope, &ctx) != SUCCESS)) { + zval_ptr_dtor_nogc(param); + ZVAL_UNDEF(param); + HANDLE_EXCEPTION(); + } + if (!Z_REFCOUNTED_P(param) && !ctx.had_side_effects) { + ZVAL_COPY_VALUE(cache_val, param); + } + } + goto recv_init_check_type; + } else { + ZVAL_COPY(param, default_value); + } + } else { +recv_init_check_type: + if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) { + SAVE_OPLINE(); + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param))) { + HANDLE_EXCEPTION(); + } + } + } + + ZEND_VM_REPEAT_OPCODE(ZEND_RECV_INIT); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_execute_data *call; + + SAVE_OPLINE(); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + +try_function_name: + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { + call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { + function_name = Z_REFVAL_P(function_name); + goto try_function_name; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + function_name = ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Value of type %s is not callable", + zend_zval_type_name(function_name)); + call = NULL; + } + + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (UNEXPECTED(EG(exception))) { + if (call) { + if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { + zend_string_release_ex(call->func->common.function_name, 0); + zend_free_trampoline(call->func); + } + zend_vm_stack_free_call_frame(call); + } + HANDLE_EXCEPTION(); + } + } else if (!call) { + HANDLE_EXCEPTION(); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RECV_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num = opline->op1.num; + zval *param; + + if (UNEXPECTED(arg_num > EX_NUM_ARGS())) { + ZEND_VM_TAIL_CALL(zend_missing_arg_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + param = EX_VAR(opline->result.var); + + if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) { + ZEND_VM_DISPATCH_TO_HELPER(zend_verify_recv_arg_type_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX param)); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RECV_VARIADIC_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num = opline->op1.num; + uint32_t arg_count = EX_NUM_ARGS(); + zval *params; + + SAVE_OPLINE(); + + params = EX_VAR(opline->result.var); + + if (arg_num <= arg_count) { + ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_VARIADIC); + ZEND_ASSERT(EX(func)->common.num_args == arg_num - 1); + zend_arg_info *arg_info = &EX(func)->common.arg_info[arg_num - 1]; + + array_init_size(params, arg_count - arg_num + 1); + zend_hash_real_init_packed(Z_ARRVAL_P(params)); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) { + zval *param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); + if (ZEND_TYPE_IS_SET(arg_info->type)) { + ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS); + do { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { + ZEND_HASH_FILL_FINISH(); + HANDLE_EXCEPTION(); + } + + if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); + ZEND_HASH_FILL_ADD(param); + param++; + } while (++arg_num <= arg_count); + } else { + do { + if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param); + ZEND_HASH_FILL_ADD(param); + param++; + } while (++arg_num <= arg_count); + } + } ZEND_HASH_FILL_END(); + } else { + ZVAL_EMPTY_ARRAY(params); + } + + if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { + zend_string *name; + zval *param; + zend_arg_info *arg_info = &EX(func)->common.arg_info[EX(func)->common.num_args]; + if (ZEND_TYPE_IS_SET(arg_info->type)) { + SEPARATE_ARRAY(params); + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param))) { + HANDLE_EXCEPTION(); + } + Z_TRY_ADDREF_P(param); + zend_hash_add_new(Z_ARRVAL_P(params), name, param); + } ZEND_HASH_FOREACH_END(); + } else if (zend_hash_num_elements(Z_ARRVAL_P(params)) == 0) { + GC_ADDREF(EX(extra_named_params)); + ZVAL_ARR(params, EX(extra_named_params)); + } else { + SEPARATE_ARRAY(params); + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) { + Z_TRY_ADDREF_P(param); + zend_hash_add_new(Z_ARRVAL_P(params), name, param); + } ZEND_HASH_FOREACH_END(); + } + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + zval *arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + +#if 0 || 0 + if (0 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline); + function(result, arg1); + } + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_1_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + zval *arg1 = get_zval_ptr_deref(opline->op1_type, opline->op1, BP_VAR_R); + if (EG(exception)) { + FREE_OP(opline->op1_type, opline->op1.var); + HANDLE_EXCEPTION(); + } + +#if 0 || 1 + if (1 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline); + function(result, arg1); + } + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_DYNAMIC_CALL_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_execute_data *call; + + SAVE_OPLINE(); + function_name = EX_VAR(opline->op2.var); + +try_function_name: + if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value); + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) { + call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value); + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) { + call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) { + function_name = Z_REFVAL_P(function_name); + goto try_function_name; + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + function_name = ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Value of type %s is not callable", + zend_zval_type_name(function_name)); + call = NULL; + } + + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + + + if (UNEXPECTED(EG(exception))) { + if (call) { + if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { + zend_string_release_ex(call->func->common.function_name, 0); + zend_free_trampoline(call->func); + } + zend_vm_stack_free_call_frame(call); + } + HANDLE_EXCEPTION(); + } + } else if (!call) { + HANDLE_EXCEPTION(); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_NOT_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + + op1 = RT_CONSTANT(opline, opline->op1); + if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_not_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_NOT_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + + val = RT_CONSTANT(opline, opline->op1); + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); + ZVAL_TRUE(EX_VAR(opline->result.var)); + if (IS_CONST == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } else { + SAVE_OPLINE(); + ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ECHO_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *z; + + SAVE_OPLINE(); + z = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_P(z) == IS_STRING) { + zend_string *str = Z_STR_P(z); + + if (ZSTR_LEN(str) != 0) { + zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); + } + } else { + zend_string *str = zval_get_string_func(z); + + if (ZSTR_LEN(str) != 0) { + zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_string_release_ex(str, 0); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPZ_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + uint8_t op1_type; + + val = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + SAVE_OPLINE(); + op1_type = IS_CONST; + if (i_zend_is_true(val)) { + opline++; + } else { + opline = OP_JMP_ADDR(opline, opline->op2); + } + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } + ZEND_VM_JMP(opline); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPNZ_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + uint8_t op1_type; + + val = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + op1_type = IS_CONST; + if (i_zend_is_true(val)) { + opline = OP_JMP_ADDR(opline, opline->op2); + } else { + opline++; + } + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } + ZEND_VM_JMP(opline); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPZ_EX_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + bool ret; + + val = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + SAVE_OPLINE(); + ret = i_zend_is_true(val); + + + if (ret) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline++; + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline = OP_JMP_ADDR(opline, opline->op2); + } + ZEND_VM_JMP(opline); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPNZ_EX_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + bool ret; + + val = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ret = i_zend_is_true(val); + + + if (ret) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline = OP_JMP_ADDR(opline, opline->op2); + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline++; + } + ZEND_VM_JMP(opline); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + retval_ptr = RT_CONSTANT(opline, opline->op1); + return_value = EX(return_value); + + + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (IS_CONST == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (IS_CONST == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } + + + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + zval observer_retval; + + retval_ptr = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R); + return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; + if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (opline->op1_type == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (opline->op1_type == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (opline->op1_type == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } + SAVE_OPLINE(); + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_BY_REF_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + SAVE_OPLINE(); + + return_value = EX(return_value); + + + do { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR)) || + (IS_CONST == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + + retval_ptr = RT_CONSTANT(opline, opline->op1); + if (!return_value) { + + + } else { + if (IS_CONST == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + break; + } + + ZVAL_NEW_REF(return_value, retval_ptr); + if (IS_CONST == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = zend_get_bad_ptr(); + + if (IS_CONST == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); + } else { + + + } + break; + } + } + + if (return_value) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); + } + + + } while (0); + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_BY_REF_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + zval observer_retval; + + SAVE_OPLINE(); + + return_value = EX(return_value); + if (!return_value) { return_value = &observer_retval; }; + do { + if ((opline->op1_type & (IS_CONST|IS_TMP_VAR)) || + (opline->op1_type == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + + retval_ptr = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + if (!return_value) { + FREE_OP(opline->op1_type, opline->op1.var); + } else { + if (opline->op1_type == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + break; + } + + ZVAL_NEW_REF(return_value, retval_ptr); + if (opline->op1_type == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = get_zval_ptr_ptr(opline->op1_type, opline->op1, BP_VAR_W); + + if (opline->op1_type == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); + } else { + FREE_OP(opline->op1_type, opline->op1.var); + } + break; + } + } + + if (return_value) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); + } + + FREE_OP(opline->op1_type, opline->op1.var); + } while (0); + + zend_observer_fcall_end(execute_data, return_value); + if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }; + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = RT_CONSTANT(opline, opline->op1); + + /* Copy return value into generator->retval */ + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (IS_CONST == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (IS_CONST == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + + EG(current_execute_data) = EX(prev_execute_data); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + + /* Copy return value into generator->retval */ + if ((opline->op1_type & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (opline->op1_type == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (opline->op1_type == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (opline->op1_type == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + zend_observer_fcall_end(generator->execute_data, &generator->retval); + + EG(current_execute_data) = EX(prev_execute_data); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_THROW_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op1); + + do { + if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + break; + } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Can only throw objects"); + + + HANDLE_EXCEPTION(); + } + } while (0); + + zend_exception_save(); + Z_TRY_ADDREF_P(value); + zend_throw_exception_object(value); + zend_exception_restore(); + + + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CATCH_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_class_entry *ce, *catch_ce; + zend_object *exception; + + SAVE_OPLINE(); + /* Check whether an exception has been thrown, if not, jump over code */ + zend_exception_restore(); + if (EG(exception) == NULL) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + catch_ce = CACHED_PTR(opline->extended_value & ~ZEND_LAST_CATCH); + if (UNEXPECTED(catch_ce == NULL)) { + catch_ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT); + + CACHE_PTR(opline->extended_value & ~ZEND_LAST_CATCH, catch_ce); + } + ce = EG(exception)->ce; + +#ifdef HAVE_DTRACE + if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { + DTRACE_EXCEPTION_CAUGHT((char *)ce->name); + } +#endif /* HAVE_DTRACE */ + + if (ce != catch_ce) { + if (!catch_ce || !instanceof_function(ce, catch_ce)) { + if (opline->extended_value & ZEND_LAST_CATCH) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + } + + exception = EG(exception); + EG(exception) = NULL; + if (RETURN_VALUE_USED(opline)) { + /* Always perform a strict assignment. There is a reasonable expectation that if you + * write "catch (Exception $e)" then $e will actually be instanceof Exception. As such, + * we should not permit coercion to string here. */ + zval tmp; + ZVAL_OBJ(&tmp, exception); + zend_assign_to_variable(EX_VAR(opline->result.var), &tmp, IS_TMP_VAR, /* strict */ 1); + } else { + OBJ_RELEASE(exception); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_USER_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg, *param; + + SAVE_OPLINE(); + + arg = RT_CONSTANT(opline, opline->op1); + param = ZEND_CALL_VAR(EX(call), opline->result.var); + if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { + zend_param_must_be_ref(EX(call)->func, opline->op2.num); + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(param, arg); + } else { + ZVAL_COPY(param, arg); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + + val = RT_CONSTANT(opline, opline->op1); + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); + ZVAL_FALSE(EX_VAR(opline->result.var)); + if (IS_CONST == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } else { + SAVE_OPLINE(); + ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CLONE_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *obj; + zend_object *zobj; + zend_class_entry *ce, *scope; + zend_function *clone; + zend_object_clone_obj_t clone_call; + + SAVE_OPLINE(); + obj = RT_CONSTANT(opline, opline->op1); + + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ + + 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)) { + obj = Z_REFVAL_P(obj); + if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { + break; + } + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj)); + + + HANDLE_EXCEPTION(); + } + } while (0); + + zobj = Z_OBJ_P(obj); + ce = zobj->ce; + clone = ce->clone; + clone_call = zobj->handlers->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CAST_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + expr = RT_CONSTANT(opline, opline->op1); + + switch (opline->extended_value) { + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(expr)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string(expr)); + break; + default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); + if (IS_CONST & (IS_VAR|IS_CV)) { + ZVAL_DEREF(expr); + } + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (opline->extended_value == IS_ARRAY) { + zend_cast_zval_to_array(result, expr, IS_CONST); + } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); + zend_cast_zval_to_object(result, expr, IS_CONST); + } + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_op_array *new_op_array; + zval *inc_filename; + + SAVE_OPLINE(); + inc_filename = RT_CONSTANT(opline, opline->op1); + new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); + if (UNEXPECTED(EG(exception) != NULL)) { + + + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (new_op_array == ZEND_FAKE_OP_ARRAY) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + } else if (UNEXPECTED(new_op_array == NULL)) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + } else if (new_op_array->last == 1 + && new_op_array->opcodes[0].opcode == ZEND_RETURN + && 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; + + ZVAL_COPY(EX_VAR(opline->result.var), RT_CONSTANT(op, op->op1)); + } + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } else { + zval *return_value = NULL; + zend_execute_data *call; + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + } + + 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, + (zend_function*)new_op_array, 0, + Z_PTR(EX(This))); + + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(); + } + + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value); + + + if (EXPECTED(zend_execute_ex == execute_ex)) { + + + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + zend_vm_stack_free_call_frame(call); + } + + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_op_array *new_op_array; + zval *inc_filename; + + SAVE_OPLINE(); + inc_filename = get_zval_ptr(opline->op1_type, opline->op1, BP_VAR_R); + new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); + if (UNEXPECTED(EG(exception) != NULL)) { + FREE_OP(opline->op1_type, opline->op1.var); + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (new_op_array == ZEND_FAKE_OP_ARRAY) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + } else if (UNEXPECTED(new_op_array == NULL)) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + } else if (new_op_array->last == 1 + && new_op_array->opcodes[0].opcode == ZEND_RETURN + && 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; + + ZVAL_COPY(EX_VAR(opline->result.var), RT_CONSTANT(op, op->op1)); + } + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } else { + zval *return_value = NULL; + zend_execute_data *call; + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + } + + 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, + (zend_function*)new_op_array, 0, + Z_PTR(EX(This))); + + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(); + } + + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value); + zend_observer_fcall_begin_specialized(call, false); + if (EXPECTED(zend_execute_ex == execute_ex)) { + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + zend_vm_stack_free_call_frame(call); + } + + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + FREE_OP(opline->op1_type, opline->op1.var); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_R_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *result; + + SAVE_OPLINE(); + + array_ptr = RT_CONSTANT(opline, opline->op1); + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CONST != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; + + + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + + + HANDLE_EXCEPTION(); + } + } + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); + } + } else { + properties = zobj->handlers->get_properties(zobj); + } + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CONST != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(result) = (uint32_t) -1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_RW_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *array_ref; + + SAVE_OPLINE(); + + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + array_ref = array_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); + } + } else { + array_ref = array_ptr = RT_CONSTANT(opline, opline->op1); + } + + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ref = EX_VAR(opline->result.var); + ZVAL_NEW_REF(array_ref, array_ptr); + array_ptr = Z_REFVAL_P(array_ref); + } + if (IS_CONST == IS_CONST) { + ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); + } else { + SEPARATE_ARRAY(array_ptr); + } + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + + + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + HashTable *properties; + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + + + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_OBJ_P(array_ptr)->properties + && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(Z_OBJ_P(array_ptr)->properties); + } + Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } + + properties = Z_OBJPROP_P(array_ptr); + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_SET_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + bool ret; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op1); + + if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + ret = i_zend_is_true(value); + + if (UNEXPECTED(EG(exception))) { + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (ret) { + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if (IS_CONST == IS_VAR && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COALESCE_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op1); + + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_CONST & IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if ((IS_CONST & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + if ((IS_CONST & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_NULL_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val, *result; + + val = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_P(val) > IS_NULL) { + do { + if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + if (Z_TYPE_P(val) <= IS_NULL) { + + + break; + } + } + ZEND_VM_NEXT_OPCODE(); + } while (0); + } + + result = EX_VAR(opline->result.var); + uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; + if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { + ZVAL_NULL(result); + if (IS_CONST == IS_CV + && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) + && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 + ) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { + ZVAL_FALSE(result); + } else { + ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); + ZVAL_TRUE(result); + } + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *result = EX_VAR(opline->result.var); + + value = RT_CONSTANT(opline, opline->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(result); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CONST == IS_CV) { + ZVAL_COPY_DEREF(result, value); + } else if (IS_CONST == IS_VAR) { + if (UNEXPECTED(Z_ISREF_P(value))) { + ZVAL_COPY_VALUE(result, Z_REFVAL_P(value)); + if (UNEXPECTED(Z_DELREF_P(value) == 0)) { + efree_size(Z_REF_P(value), sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } else { + ZVAL_COPY_VALUE(result, value); + } + } else { + ZVAL_COPY_VALUE(result, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { + Z_ADDREF_P(result); + } + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_CLASS_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + do_bind_class(RT_CONSTANT(opline, opline->op1), (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_function *func; + zval *object; + zend_class_entry *called_scope; + + func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num]; + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) || + (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) { + object = NULL; + } else { + object = &EX(This); + } + } else { + called_scope = Z_CE(EX(This)); + object = NULL; + } + SAVE_OPLINE(); + zend_create_closure(EX_VAR(opline->result.var), func, + EX(func)->op_array.scope, called_scope, object); + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_FROM_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *val; + + SAVE_OPLINE(); + val = RT_CONSTANT(opline, opline->op1); + + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + +yield_from_try_again: + if (Z_TYPE_P(val) == IS_ARRAY) { + ZVAL_COPY_VALUE(&generator->values, val); + if (Z_OPT_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); + } + Z_FE_POS(generator->values) = 0; + + + } else if (IS_CONST != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(val); + if (ce == zend_ce_generator) { + zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); + + Z_ADDREF_P(val); + + + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zend_object_iterator *iter = ce->get_iterator(ce, val, 0); + + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (!EG(exception)) { + zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(&generator->values, &iter->std); + } + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; + } else { + zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + /* This is the default return value + * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_STRLEN_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = RT_CONSTANT(opline, opline->op1); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(value); + } + ZEND_VM_NEXT_OPCODE(); + } else { + bool strict; + + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + + + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = ZVAL_UNDEFINED_OP1(); + } + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + zend_string *str; + zval tmp; + + if (UNEXPECTED(Z_TYPE_P(value) == IS_NULL)) { + zend_error(E_DEPRECATED, + "strlen(): Passing null to parameter #1 ($string) of type string is deprecated"); + ZVAL_LONG(EX_VAR(opline->result.var), 0); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + break; + } + + ZVAL_COPY(&tmp, value); + if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); + zval_ptr_dtor(&tmp); + break; + } + zval_ptr_dtor(&tmp); + } + if (!EG(exception)) { + zend_type_error("strlen(): Argument #1 ($string) must be of type string, %s given", zend_zval_value_name(value)); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } while (0); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_TYPE_CHECK_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + int result = 0; + + value = RT_CONSTANT(opline, opline->op1); + if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { +type_check_resource: + if (opline->extended_value != MAY_BE_RESOURCE + || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { + result = 1; + } + } else if ((IS_CONST & (IS_CV|IS_VAR)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { + goto type_check_resource; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + result = ((1 << IS_NULL) & opline->extended_value) != 0; + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + + + ZEND_VM_SMART_BRANCH(result, 1); + } else { + ZEND_VM_SMART_BRANCH(result, 0); + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DEFINED_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_constant *c; + + c = CACHED_PTR(opline->extended_value); + if (EXPECTED(c != NULL)) { + if (!IS_SPECIAL_CACHE_VAL(c)) { +defined_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) { +defined_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } + if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { + CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants)))); + goto defined_false; + } else { + goto defined_true; + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_FRAMELESS_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_jmp_fl_result result = (uintptr_t)CACHED_PTR(opline->extended_value); +try_again: + if (EXPECTED(result == ZEND_JMP_FL_HIT)) { + OPLINE = OP_JMP_ADDR(opline, opline->op2); + ZEND_VM_CONTINUE(); + } else if (EXPECTED(result == ZEND_JMP_FL_MISS)) { + ZEND_VM_NEXT_OPCODE(); + } else { + ZEND_ASSERT(result == ZEND_JMP_FL_UNPRIMED); + /* func_name refers to the function in the local namespace, e.g. foo\substr. */ + zval *func_name = (zval *)RT_CONSTANT(opline, opline->op1); + /* If it cannot be found locally, we must be referring to the global function. */ + zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name)); + /* ZEND_JMP_FL_MISS = 1, ZEND_JMP_FL_HIT = 2 */ + result = (func == NULL) + 1; + CACHE_PTR(opline->extended_value, (void *)result); + goto try_again; + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_LONG_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(value)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_DOUBLE(EX_VAR(opline->result.var), Z_DVAL_P(value)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_NOREF_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_SIMPLE_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + value = RT_CONSTANT(opline, opline->op1); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, value); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num = opline->op2.num; + + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + } + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_add_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto add_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +add_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 + d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto add_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_sub_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto sub_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +sub_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 - d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto sub_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + zend_long overflow; + + result = EX_VAR(opline->result.var); + ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow); + Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto mul_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +mul_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 * d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto mul_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + div_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MOD_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + if (UNEXPECTED(Z_LVAL_P(op2) == 0)) { + ZEND_VM_TAIL_CALL(zend_mod_by_zero_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) { + /* Prevent overflow error/crash if op1==ZEND_LONG_MIN */ + ZVAL_LONG(result, 0); + } else { + ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2)); + } + ZEND_VM_NEXT_OPCODE(); + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SR_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) >> Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + pow_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_not_identical_function(op1, op2); + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + compare_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_OR_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) | Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_AND_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) & Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_XOR_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) ^ Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_XOR_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, RT_CONSTANT(opline, opline->op2)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_CONST & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_CONST & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CONST == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_R_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + zend_fetch_dimension_address_LIST_r(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if (IS_CONST == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST != IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_CONST == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CONST & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CONST != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + zend_invalid_method_call(object, function_name); + + + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CONST != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_CONST == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_CONST == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_CONST != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_CONST == IS_CONST && + IS_CONST == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_CONST != IS_CONST && + IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_CONST != IS_UNUSED) { + function_name = RT_CONSTANT(opline, opline->op2); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CONST != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_USER_CALL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_fcall_info_cache fcc; + char *error = NULL; + zend_function *func; + void *object_or_called_scope; + zend_execute_data *call; + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; + + SAVE_OPLINE(); + function_name = RT_CONSTANT(opline, opline->op2); + if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); + + /* Deprecation can be emitted from zend_is_callable_ex(), which can + * invoke a user error handler and throw an exception. + * For the CONST and CV case we reuse the same exception block below + * to make sure we don't increase VM size too much. */ + if (!(IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + + + HANDLE_EXCEPTION(); + } + + func = fcc.function_handler; + object_or_called_scope = fcc.called_scope; + if (func->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); + call_info |= ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; + } + + + if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + if (call_info & ZEND_CALL_CLOSURE) { + zend_object_release(ZEND_CLOSURE_OBJECT(func)); + } else if (call_info & ZEND_CALL_RELEASE_THIS) { + zend_object_release(fcc.object); + } + HANDLE_EXCEPTION(); + } + + if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) { + init_func_run_time_cache(&func->op_array); + } + } else { + zend_type_error("%s(): Argument #1 ($callback) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + efree(error); + + + HANDLE_EXCEPTION(); + } + + call = zend_vm_stack_push_call_frame(call_info, + func, opline->extended_value, object_or_called_scope); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_EX_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + } + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv, *constant_zv; + zend_string *constant_name; + USE_OPLINE + + SAVE_OPLINE(); + + do { + if (IS_CONST == IS_CONST && IS_CONST == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + } + if (IS_CONST == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value))) { + ce = CACHED_PTR(opline->extended_value); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->extended_value, ce); + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (IS_CONST != IS_CONST + && IS_CONST == IS_CONST + && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + + constant_zv = RT_CONSTANT(opline, opline->op2); + if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { + zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + constant_name = Z_STR_P(constant_zv); + /* Magic 'class' for constant OP2 is caught at compile-time */ + if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + + + ZEND_VM_NEXT_OPCODE(); + } + zv = IS_CONST == IS_CONST + ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) + : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); + + if (EXPECTED(zv != NULL)) { + c = Z_PTR_P(zv); + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + + bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + if (c->ce->type == ZEND_USER_CLASS) { + /* Recursion protection only applied to user constants, GH-18463 */ + CONST_PROTECT_RECURSION(c); + } + zend_deprecated_class_constant(c, constant_name); + if (c->ce->type == ZEND_USER_CLASS) { + CONST_UNPROTECT_RECURSION(c); + } + + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + + value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST && !is_constant_deprecated) { + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } + } else { + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } while (0); + + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = RT_CONSTANT(opline, opline->op1); + if (IS_CONST == IS_TMP_VAR) { + /* pass */ + } else if (IS_CONST == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CONST == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CONST == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CONST != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + offset = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, IS_CONST == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if (IS_CONST & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + offset = RT_CONSTANT(opline, opline->op2); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = RT_CONSTANT(opline, opline->op1); + subject = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_class_entry *ce = CACHED_PTR(opline->extended_value); + if (ce == NULL) { + zval *lcname = RT_CONSTANT(opline, opline->op1); + zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1)); + if (zv) { + SAVE_OPLINE(); + ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2))); + if (EG(exception)) { + HANDLE_EXCEPTION(); + } + } + CACHE_PTR(opline->extended_value, ce); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_CONST_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *name; + zval *val; + zend_constant c; + + SAVE_OPLINE(); + name = RT_CONSTANT(opline, opline->op1); + val = RT_CONSTANT(opline, opline->op2); + + ZVAL_COPY(&c.value, val); + if (Z_OPT_CONSTANT(c.value)) { + if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) { + zval_ptr_dtor_nogc(&c.value); + + + + + HANDLE_EXCEPTION(); + } + } + /* non persistent, case sensitive */ + ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); + c.name = zend_string_copy(Z_STR_P(name)); + + if (zend_register_constant(&c) == NULL) { + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *name; + zval *val; + zend_constant c, *registered; + + SAVE_OPLINE(); + name = RT_CONSTANT(opline, opline->op1); + val = RT_CONSTANT(opline, opline->op2); + + ZVAL_COPY(&c.value, val); + if (Z_OPT_CONSTANT(c.value)) { + if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) { + zval_ptr_dtor_nogc(&c.value); + + + + + HANDLE_EXCEPTION(); + } + } + /* non persistent, case sensitive */ + ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT); + c.name = zend_string_copy(Z_STR_P(name)); + + registered = zend_register_constant(&c); + if (registered == NULL) { + + + + + /* two opcodes used, second one is the data with attributes */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } + + HashTable *attributes = Z_PTR_P(get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1)); + ZEND_ASSERT(attributes != NULL); + zend_constant_add_attributes(registered, attributes); + + + + + /* two opcodes used, second one is the data with attributes */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CONST == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = RT_CONSTANT(opline, opline->op1); + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + zval *key = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SWITCH_LONG_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_P(op) != IS_LONG) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_LONG) { + /* Wrong type, fall back to ZEND_CASE chain */ + ZEND_VM_NEXT_OPCODE(); + } + } + + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SWITCH_STRING_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = RT_CONSTANT(opline, opline->op1); + + if (Z_TYPE_P(op) != IS_STRING) { + if (IS_CONST == IS_CONST) { + /* Wrong type, fall back to ZEND_CASE chain */ + ZEND_VM_NEXT_OPCODE(); + } else { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_STRING) { + /* Wrong type, fall back to ZEND_CASE chain */ + ZEND_VM_NEXT_OPCODE(); + } + } + } + + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), IS_CONST == IS_CONST); + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MATCH_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = RT_CONSTANT(opline, opline->op1); + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + +match_try_again: + if (Z_TYPE_P(op) == IS_LONG) { + jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); + } else if (Z_TYPE_P(op) == IS_STRING) { + jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), IS_CONST == IS_CONST); + } else if (Z_TYPE_P(op) == IS_REFERENCE) { + op = Z_REFVAL_P(op); + goto match_try_again; + } else { + if (UNEXPECTED((IS_CONST & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) { + SAVE_OPLINE(); + op = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + goto match_try_again; + } + + goto default_branch; + } + + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { +default_branch: + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IN_ARRAY_SPEC_CONST_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; + + op1 = RT_CONSTANT(opline, opline->op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_CONST == IS_CONST); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + ZEND_VM_SMART_BRANCH(result, 0); + } + + if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); + } + SAVE_OPLINE(); + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + + + ZEND_VM_SMART_BRANCH(result, 0); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); + ZEND_VM_SMART_BRANCH(result, 0); + } else { + zend_string *key; + zval key_tmp; + + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } + + SAVE_OPLINE(); + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + + + ZEND_VM_SMART_BRANCH(1, 1); + } + } ZEND_HASH_FOREACH_END(); + } + + + ZEND_VM_SMART_BRANCH(0, 1); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_add_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto add_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +add_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 + d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto add_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_sub_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto sub_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +sub_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 - d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto sub_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MOD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + if (UNEXPECTED(Z_LVAL_P(op2) == 0)) { + ZEND_VM_TAIL_CALL(zend_mod_by_zero_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) { + /* Prevent overflow error/crash if op1==ZEND_LONG_MIN */ + ZVAL_LONG(result, 0); + } else { + ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2)); + } + ZEND_VM_NEXT_OPCODE(); + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SR_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) >> Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv, *constant_zv; + zend_string *constant_name; + USE_OPLINE + + SAVE_OPLINE(); + + do { + if (IS_CONST == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + } + if (IS_CONST == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value))) { + ce = CACHED_PTR(opline->extended_value); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->extended_value, ce); + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (IS_CONST != IS_CONST + && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + + constant_zv = _get_zval_ptr_tmpvarcv(opline->op2_type, opline->op2, BP_VAR_R EXECUTE_DATA_CC); + if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { + zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + constant_name = Z_STR_P(constant_zv); + /* Magic 'class' for constant OP2 is caught at compile-time */ + if ((IS_TMP_VAR|IS_VAR|IS_CV) != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); + } + zv = (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) + : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); + + if (EXPECTED(zv != NULL)) { + c = Z_PTR_P(zv); + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + + bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + if (c->ce->type == ZEND_USER_CLASS) { + /* Recursion protection only applied to user constants, GH-18463 */ + CONST_PROTECT_RECURSION(c); + } + zend_deprecated_class_constant(c, constant_name); + if (c->ce->type == ZEND_USER_CLASS) { + CONST_UNPROTECT_RECURSION(c); + } + + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + + value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && !is_constant_deprecated) { + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } + } else { + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } while (0); + + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + fast_long_sub_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; + + container = RT_CONSTANT(opline, opline->op1); + dim = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_index_array: + if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { + offset = Z_LVAL_P(dim); + } else { + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ht = Z_ARRVAL_P(container); + ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_index_array; + } else { + goto fetch_dim_r_index_slow; + } + } else { +fetch_dim_r_index_slow: + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + +fetch_dim_r_index_undef: + ZVAL_NULL(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + zend_undefined_offset(offset); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + div_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (IS_CONST != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_CONST & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_CONST & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = RT_CONSTANT(opline, opline->op1); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_CONST == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CONST & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + zend_invalid_method_call(object, function_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + 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); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_CONST == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_CONST == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_CONST == IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_CONST != IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_fcall_info_cache fcc; + char *error = NULL; + zend_function *func; + void *object_or_called_scope; + zend_execute_data *call; + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; + + SAVE_OPLINE(); + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); + + /* Deprecation can be emitted from zend_is_callable_ex(), which can + * invoke a user error handler and throw an exception. + * For the CONST and CV case we reuse the same exception block below + * to make sure we don't increase VM size too much. */ + if (!((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + func = fcc.function_handler; + object_or_called_scope = fcc.called_scope; + if (func->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); + call_info |= ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + if (call_info & ZEND_CALL_CLOSURE) { + zend_object_release(ZEND_CLOSURE_OBJECT(func)); + } else if (call_info & ZEND_CALL_RELEASE_THIS) { + zend_object_release(fcc.object); + } + HANDLE_EXCEPTION(); + } + + if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) { + init_func_run_time_cache(&func->op_array); + } + } else { + zend_type_error("%s(): Argument #1 ($callback) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + efree(error); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + call = zend_vm_stack_push_call_frame(call_info, + func, opline->extended_value, object_or_called_scope); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = RT_CONSTANT(opline, opline->op1); + if (IS_CONST == IS_TMP_VAR) { + /* pass */ + } else if (IS_CONST == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CONST == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CONST == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CONST != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if (IS_CONST & (IS_CONST|IS_CV)) { + /* avoid exception check */ + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = RT_CONSTANT(opline, opline->op1); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CONST == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = RT_CONSTANT(opline, opline->op1); + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_R_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_W_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_RW_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + int fetch_type = + (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? + BP_VAR_W : BP_VAR_R; + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_IS_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_CONST == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_UNUSED != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_CONST == IS_CONST && + IS_UNUSED == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_CONST != IS_CONST && + IS_UNUSED == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_UNUSED != IS_UNUSED) { + function_name = NULL; + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_UNUSED == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_UNUSED != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (IS_CONST == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_CONST != IS_UNUSED) + USE_OPLINE + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST) { + ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); + retval_ref = retval_ptr = EX_VAR(opline->result.var); + } else if (IS_CONST == IS_VAR) { + if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_CONST == IS_CV) { + ZVAL_DEREF(retval_ptr); + } + + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); + } else { + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; + } + } + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + } + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + } + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NEW_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *result; + zend_function *constructor; + zend_class_entry *ce; + zend_execute_data *call; + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + ce = CACHED_PTR(opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->op2.num, ce); + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { + ZVAL_UNDEF(result); + HANDLE_EXCEPTION(); + } + + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); + if (constructor == NULL) { + /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next + * opcode is DO_FCALL in case EXT instructions are used. */ + if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } + + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + + /* Perform a dummy function call */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, + opline->extended_value, NULL); + } else { + if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { + init_func_run_time_cache(&constructor->op_array); + } + /* We are not handling overloaded classes right now */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, + constructor, + opline->extended_value, + Z_OBJ_P(result)); + Z_ADDREF_P(result); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = RT_CONSTANT(opline, opline->op1); + if (IS_CONST == IS_TMP_VAR) { + /* pass */ + } else if (IS_CONST == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CONST == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CONST == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_UNUSED != IS_UNUSED) { + zval *offset = NULL; + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CONST != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_VAR_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + + varname = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + + + HANDLE_EXCEPTION(); + } + } + + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + zend_hash_del_ind(target_symbol_table, name); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + bool result; + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + varname = RT_CONSTANT(opline, opline->op1); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(varname); + } else { + name = zval_get_tmp_string(varname, &tmp_name); + } + + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + value = zend_hash_find_ex(target_symbol_table, name, IS_CONST == IS_CONST); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + + if (!value) { + result = (opline->extended_value & ZEND_ISEMPTY); + } else { + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + if (Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + } + result = Z_TYPE_P(value) > IS_NULL; + } else { + result = !i_zend_is_true(value); + } + } + + ZEND_VM_SMART_BRANCH(result, true); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CONST == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = RT_CONSTANT(opline, opline->op1); + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + zval *key = NULL; + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op; + + SAVE_OPLINE(); + op = RT_CONSTANT(opline, opline->op1); + zend_match_unhandled_error(op); + HANDLE_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COUNT_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_long count; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + + while (1) { + if (Z_TYPE_P(op1) == IS_ARRAY) { + count = zend_hash_num_elements(Z_ARRVAL_P(op1)); + break; + } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + + /* first, we check if the handler is defined */ + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { + break; + } + if (UNEXPECTED(EG(exception))) { + count = 0; + break; + } + } + + /* if not and the object implements Countable we call its count() method */ + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { + zval retval; + + zend_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); + zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval); + count = zval_get_long(&retval); + zval_ptr_dtor(&retval); + break; + } + + /* If There's no handler and it doesn't implement Countable then emit a TypeError */ + } else if ((IS_CONST & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + count = 0; + zend_type_error("%s(): Argument #1 ($value) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_value_name(op1)); + break; + } + + ZVAL_LONG(EX_VAR(opline->result.var), count); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_CLASS_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (IS_CONST == IS_UNUSED) { + SAVE_OPLINE(); + if (UNEXPECTED(!EX(func)->common.scope)) { + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } else { + zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated"); + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zval *op1; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + while (1) { + if (Z_TYPE_P(op1) == IS_OBJECT) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); + } else if ((IS_CONST & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + break; + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_TYPE_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + type = zend_zval_get_legacy_type(op1); + if (EXPECTED(type)) { + ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); + } else { + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_array *ht; + uint32_t arg_count, result_size, skip; + + arg_count = EX_NUM_ARGS(); + if (IS_CONST == IS_CONST) { + skip = Z_LVAL_P(RT_CONSTANT(opline, opline->op1)); + if (arg_count < skip) { + result_size = 0; + } else { + result_size = arg_count - skip; + } + } else { + skip = 0; + result_size = arg_count; + } + + if (result_size) { + SAVE_OPLINE(); + uint32_t first_extra_arg = EX(func)->op_array.num_args; + + ht = zend_new_array(result_size); + ZVAL_ARR(EX_VAR(opline->result.var), ht); + zend_hash_real_init_packed(ht); + ZEND_HASH_FILL_PACKED(ht) { + zval *p, *q; + uint32_t i = skip; + p = EX_VAR_NUM(i); + if (arg_count > first_extra_arg) { + while (i < first_extra_arg) { + q = p; + if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) { + ZVAL_DEREF(q); + if (Z_OPT_REFCOUNTED_P(q)) { + Z_ADDREF_P(q); + } + ZEND_HASH_FILL_SET(q); + } else { + ZEND_HASH_FILL_SET_NULL(); + } + ZEND_HASH_FILL_NEXT(); + p++; + i++; + } + if (skip < first_extra_arg) { + skip = 0; + } else { + skip -= first_extra_arg; + } + p = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T + skip); + } + while (i < arg_count) { + q = p; + if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) { + ZVAL_DEREF(q); + if (Z_OPT_REFCOUNTED_P(q)) { + Z_ADDREF_P(q); + } + ZEND_HASH_FILL_SET(q); + } else { + ZEND_HASH_FILL_SET_NULL(); + } + ZEND_HASH_FILL_NEXT(); + p++; + i++; + } + } ZEND_HASH_FILL_END(); + ht->nNumOfElements = result_size; + } else { + ZVAL_EMPTY_ARRAY(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE(); +} + +/* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zend_class_entry *ce = EX(func)->common.scope; + ZEND_ASSERT(ce); + + zend_class_entry *parent_ce = ce->parent; + if (!parent_ce) { + zend_throw_error(NULL, "Cannot use \"parent\" when current class scope has no parent"); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + zend_string *property_name = Z_STR_P(RT_CONSTANT(opline, opline->op1)); + zend_property_hook_kind hook_kind = opline->op2.num; + + zend_property_info *prop_info = zend_hash_find_ptr(&parent_ce->properties_info, property_name); + if (!prop_info) { + zend_throw_error(NULL, "Undefined property %s::$%s", ZSTR_VAL(parent_ce->name), ZSTR_VAL(property_name)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (prop_info->flags & ZEND_ACC_PRIVATE) { + zend_throw_error(NULL, "Cannot access private property %s::$%s", ZSTR_VAL(parent_ce->name), ZSTR_VAL(property_name)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + zend_function **hooks = prop_info->hooks; + zend_function *hook = hooks ? hooks[hook_kind] : NULL; + + zend_execute_data *call; + if (hook) { + call = zend_vm_stack_push_call_frame( + ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS, + hook, opline->extended_value, Z_OBJ_P(ZEND_THIS)); + if (EXPECTED(hook->type == ZEND_USER_FUNCTION)) { + if (UNEXPECTED(!RUN_TIME_CACHE(&hook->op_array))) { + init_func_run_time_cache(&hook->op_array); + } + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + } + } else { + zend_function *fbc = zend_get_property_hook_trampoline(prop_info, hook_kind, property_name); + call = zend_vm_stack_push_call_frame( + ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS, + fbc, opline->extended_value, Z_OBJ_P(ZEND_THIS)); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + div_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + + if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = RT_CONSTANT(opline, opline->op1); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + dim = EX_VAR(opline->op2.var); + if (IS_CONST != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_CONST & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_CONST & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CV == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CONST & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_R_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + zend_fetch_dimension_address_LIST_r(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = RT_CONSTANT(opline, opline->op1); + op2 = EX_VAR(opline->op2.var); + if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if (IS_CV == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if (IS_CV != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = RT_CONSTANT(opline, opline->op1); + + if (IS_CV != IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_CONST == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CONST & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CV != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + zend_invalid_method_call(object, function_name); + + + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CV != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_CONST == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_CONST == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_CV != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_CONST == IS_CONST && + IS_CV == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_CONST != IS_CONST && + IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_CV != IS_UNUSED) { + function_name = EX_VAR(opline->op2.var); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CV != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_CONST == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_USER_CALL_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_fcall_info_cache fcc; + char *error = NULL; + zend_function *func; + void *object_or_called_scope; + zend_execute_data *call; + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; + + SAVE_OPLINE(); + function_name = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) { + ZEND_ASSERT(!error); + + /* Deprecation can be emitted from zend_is_callable_ex(), which can + * invoke a user error handler and throw an exception. + * For the CONST and CV case we reuse the same exception block below + * to make sure we don't increase VM size too much. */ + if (!(IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + + + HANDLE_EXCEPTION(); + } + + func = fcc.function_handler; + object_or_called_scope = fcc.called_scope; + if (func->common.fn_flags & ZEND_ACC_CLOSURE) { + /* Delay closure destruction until its invocation */ + GC_ADDREF(ZEND_CLOSURE_OBJECT(func)); + call_info |= ZEND_CALL_CLOSURE; + if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + call_info |= ZEND_CALL_FAKE_CLOSURE; + } + if (fcc.object) { + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_HAS_THIS; + } + } else if (fcc.object) { + GC_ADDREF(fcc.object); /* For $this pointer */ + object_or_called_scope = fcc.object; + call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS; + } + + + if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) { + if (call_info & ZEND_CALL_CLOSURE) { + zend_object_release(ZEND_CLOSURE_OBJECT(func)); + } else if (call_info & ZEND_CALL_RELEASE_THIS) { + zend_object_release(fcc.object); + } + HANDLE_EXCEPTION(); + } + + if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) { + init_func_run_time_cache(&func->op_array); + } + } else { + zend_type_error("%s(): Argument #1 ($callback) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error); + efree(error); + + + HANDLE_EXCEPTION(); + } + + call = zend_vm_stack_push_call_frame(call_info, + func, opline->extended_value, object_or_called_scope); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = RT_CONSTANT(opline, opline->op1); + if (IS_CONST == IS_TMP_VAR) { + /* pass */ + } else if (IS_CONST == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CONST == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CONST == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CV != IS_UNUSED) { + zval *offset = EX_VAR(opline->op2.var); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CONST != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + offset = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, IS_CV == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if (IS_CONST & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = RT_CONSTANT(opline, opline->op1); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + if (IS_CONST == IS_CONST || + (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = RT_CONSTANT(opline, opline->op1); + subject = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CONST_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = RT_CONSTANT(opline, opline->op1); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CONST == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = RT_CONSTANT(opline, opline->op1); + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CONST == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_NOT_SPEC_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + + op1 = EX_VAR(opline->op1.var); + if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_not_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = EX_VAR(opline->op1.var); + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(value)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = EX_VAR(opline->op1.var); + ZVAL_DOUBLE(EX_VAR(opline->result.var), Z_DVAL_P(value)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = EX_VAR(opline->op1.var); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_add_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto add_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +add_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 + d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto add_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_sub_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto sub_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +sub_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 - d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto sub_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + zend_long overflow; + + result = EX_VAR(opline->result.var); + ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow); + Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto mul_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +mul_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 * d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto mul_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MOD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + if (UNEXPECTED(Z_LVAL_P(op2) == 0)) { + ZEND_VM_TAIL_CALL(zend_mod_by_zero_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) { + /* Prevent overflow error/crash if op1==ZEND_LONG_MIN */ + ZVAL_LONG(result, 0); + } else { + ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2)); + } + ZEND_VM_NEXT_OPCODE(); + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) >> Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_OR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) | Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_AND_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) & Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_XOR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) ^ Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_LIST_r(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = EX_VAR(opline->op1.var); + + if (Z_TYPE_P(op) != IS_LONG) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_LONG) { + /* Wrong type, fall back to ZEND_CASE chain */ + ZEND_VM_NEXT_OPCODE(); + } + } + + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = EX_VAR(opline->op1.var); + + if (Z_TYPE_P(op) != IS_STRING) { + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* Wrong type, fall back to ZEND_CASE chain */ + ZEND_VM_NEXT_OPCODE(); + } else { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_STRING) { + /* Wrong type, fall back to ZEND_CASE chain */ + ZEND_VM_NEXT_OPCODE(); + } + } + } + + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST); + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MATCH_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op, *jump_zv; + HashTable *jumptable; + + op = EX_VAR(opline->op1.var); + jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + +match_try_again: + if (Z_TYPE_P(op) == IS_LONG) { + jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op)); + } else if (Z_TYPE_P(op) == IS_STRING) { + jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST); + } else if (Z_TYPE_P(op) == IS_REFERENCE) { + op = Z_REFVAL_P(op); + goto match_try_again; + } else { + if (UNEXPECTED(((IS_TMP_VAR|IS_VAR|IS_CV) & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) { + SAVE_OPLINE(); + op = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + goto match_try_again; + } + + goto default_branch; + } + + if (jump_zv != NULL) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv)); + ZEND_VM_CONTINUE(); + } else { +default_branch: + /* default */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + fast_long_add_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + fast_long_sub_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + ZVAL_LONG(result, Z_LVAL_P(op1) * Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + zend_long overflow; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow); + Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + bool result; + + op1 = _get_zval_ptr_tmpvarcv(opline->op1_type, opline->op1, BP_VAR_R EXECUTE_DATA_CC); + result = Z_TYPE_P(op1) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(op1)) == 0; + FREE_OP(opline->op1_type, opline->op1.var); + + + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + bool result; + + op1 = _get_zval_ptr_tmpvarcv(opline->op1_type, opline->op1, BP_VAR_R EXECUTE_DATA_CC); + result = Z_TYPE_P(op1) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(op1)) == 0; + FREE_OP(opline->op1_type, opline->op1.var); + + + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + bool result; + + op1 = _get_zval_ptr_tmpvarcv(opline->op1_type, opline->op1, BP_VAR_R EXECUTE_DATA_CC); + result = Z_TYPE_P(op1) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(op1)) == 0; + FREE_OP(opline->op1_type, opline->op1.var); + + + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + bool result; + + op1 = _get_zval_ptr_tmpvarcv(opline->op1_type, opline->op1, BP_VAR_R EXECUTE_DATA_CC); + result = Z_TYPE_P(op1) != IS_ARRAY || zend_hash_num_elements(Z_ARR_P(op1)) > 0; + FREE_OP(opline->op1_type, opline->op1.var); + + + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + bool result; + + op1 = _get_zval_ptr_tmpvarcv(opline->op1_type, opline->op1, BP_VAR_R EXECUTE_DATA_CC); + result = Z_TYPE_P(op1) != IS_ARRAY || zend_hash_num_elements(Z_ARR_P(op1)) > 0; + FREE_OP(opline->op1_type, opline->op1.var); + + + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + bool result; + + op1 = _get_zval_ptr_tmpvarcv(opline->op1_type, opline->op1, BP_VAR_R EXECUTE_DATA_CC); + result = Z_TYPE_P(op1) != IS_ARRAY || zend_hash_num_elements(Z_ARR_P(op1)) > 0; + FREE_OP(opline->op1_type, opline->op1.var); + + + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_add_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto add_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +add_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 + d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto add_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + fast_long_sub_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto sub_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +sub_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 - d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto sub_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + zend_long overflow; + + result = EX_VAR(opline->result.var); + ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow); + Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto mul_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +mul_double: + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, d1 * d2); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto mul_double; + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + result = EX_VAR(opline->result.var); + if (UNEXPECTED(Z_LVAL_P(op2) == 0)) { + ZEND_VM_TAIL_CALL(zend_mod_by_zero_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) { + /* Prevent overflow error/crash if op1==ZEND_LONG_MIN */ + ZVAL_LONG(result, 0); + } else { + ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2)); + } + ZEND_VM_NEXT_OPCODE(); + } + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + /* Perform shift on unsigned numbers to get well-defined wrap behavior. */ + ZVAL_LONG(EX_VAR(opline->result.var), + (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) + && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) >> Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { +is_smaller_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_smaller_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_double: + if (d1 < d2) { + goto is_smaller_true; + } else { + goto is_smaller_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { +is_smaller_or_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else { +is_smaller_or_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + ZVAL_FALSE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_smaller_or_equal_double; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_smaller_or_equal_double: + if (d1 <= d2) { + goto is_smaller_or_equal_true; + } else { + goto is_smaller_or_equal_false; + } + } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_smaller_or_equal_double; + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) | Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) & Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) + && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) ^ Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + fast_long_add_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + fast_long_sub_function(result, op1, op2); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_LONG(result, Z_LVAL_P(op1) * Z_LVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + zend_long overflow; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow); + Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2, *result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = EX_VAR(opline->result.var); + ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) != Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) != Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) < Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) < Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_NONE(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPZ(result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2)); + ZEND_VM_SMART_BRANCH_JMPNZ(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_LIST_r(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op; + + SAVE_OPLINE(); + op = EX_VAR(opline->op1.var); + zend_match_unhandled_error(op); + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_LIST_r(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_NOT_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); + ZVAL_TRUE(EX_VAR(opline->result.var)); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } else { + SAVE_OPLINE(); + ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ECHO_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *z; + + SAVE_OPLINE(); + z = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_P(z) == IS_STRING) { + zend_string *str = Z_STR_P(z); + + if (ZSTR_LEN(str) != 0) { + zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); + } + } else { + zend_string *str = zval_get_string_func(z); + + if (ZSTR_LEN(str) != 0) { + zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_string_release_ex(str, 0); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPZ_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + uint8_t op1_type; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); + if (i_zend_is_true(val)) { + opline++; + } else { + opline = OP_JMP_ADDR(opline, opline->op2); + } + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } + ZEND_VM_JMP(opline); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPNZ_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + uint8_t op1_type; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + op1_type = (IS_TMP_VAR|IS_VAR); + if (i_zend_is_true(val)) { + opline = OP_JMP_ADDR(opline, opline->op2); + } else { + opline++; + } + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } + ZEND_VM_JMP(opline); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPZ_EX_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + bool ret; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + SAVE_OPLINE(); + ret = i_zend_is_true(val); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (ret) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline++; + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline = OP_JMP_ADDR(opline, opline->op2); + } + ZEND_VM_JMP(opline); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPNZ_EX_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + bool ret; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ret = i_zend_is_true(val); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (ret) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline = OP_JMP_ADDR(opline, opline->op2); + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline++; + } + ZEND_VM_JMP(opline); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FREE_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_FREE_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *var; + USE_OPLINE + + var = EX_VAR(opline->op1.var); + if (Z_TYPE_P(var) != IS_ARRAY) { + SAVE_OPLINE(); + if (Z_FE_ITER_P(var) != (uint32_t)-1) { + zend_hash_iterator_del(Z_FE_ITER_P(var)); + } + zval_ptr_dtor_nogc(var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + /* This is freeing an array. Use an inlined version of zval_ptr_dtor_nogc. */ + /* PHP only needs to save the opline and check for an exception if the last reference to the array was garbage collected (destructors of elements in the array could throw an exception) */ + if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_THROW_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + do { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Can only throw objects"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } while (0); + + zend_exception_save(); + Z_TRY_ADDREF_P(value); + zend_throw_exception_object(value); + zend_exception_restore(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); + ZVAL_FALSE(EX_VAR(opline->result.var)); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } else { + SAVE_OPLINE(); + ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CLONE_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *obj; + zend_object *zobj; + zend_class_entry *ce, *scope; + zend_function *clone; + zend_object_clone_obj_t clone_call; + + SAVE_OPLINE(); + obj = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ + + 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)) { + obj = Z_REFVAL_P(obj); + if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { + break; + } + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } while (0); + + zobj = Z_OBJ_P(obj); + ce = zobj->ce; + clone = ce->clone; + clone_call = zobj->handlers->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_op_array *new_op_array; + zval *inc_filename; + + SAVE_OPLINE(); + inc_filename = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (new_op_array == ZEND_FAKE_OP_ARRAY) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + } else if (UNEXPECTED(new_op_array == NULL)) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + } else if (new_op_array->last == 1 + && new_op_array->opcodes[0].opcode == ZEND_RETURN + && 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; + + ZVAL_COPY(EX_VAR(opline->result.var), RT_CONSTANT(op, op->op1)); + } + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } else { + zval *return_value = NULL; + zend_execute_data *call; + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + } + + 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, + (zend_function*)new_op_array, 0, + Z_PTR(EX(This))); + + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(); + } + + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value); + + + if (EXPECTED(zend_execute_ex == execute_ex)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + zend_vm_stack_free_call_frame(call); + } + + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_FROM_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + +yield_from_try_again: + if (Z_TYPE_P(val) == IS_ARRAY) { + ZVAL_COPY_VALUE(&generator->values, val); + if (Z_OPT_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); + } + Z_FE_POS(generator->values) = 0; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(val); + if (ce == zend_ce_generator) { + zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); + + Z_ADDREF_P(val); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zend_object_iterator *iter = ce->get_iterator(ce, val, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (!EG(exception)) { + zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(&generator->values, &iter->std); + } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; + } else { + zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + /* This is the default return value + * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_STRLEN_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(value); + } + ZEND_VM_NEXT_OPCODE(); + } else { + bool strict; + + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = ZVAL_UNDEFINED_OP1(); + } + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + zend_string *str; + zval tmp; + + if (UNEXPECTED(Z_TYPE_P(value) == IS_NULL)) { + zend_error(E_DEPRECATED, + "strlen(): Passing null to parameter #1 ($string) of type string is deprecated"); + ZVAL_LONG(EX_VAR(opline->result.var), 0); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + break; + } + + ZVAL_COPY(&tmp, value); + if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); + zval_ptr_dtor(&tmp); + break; + } + zval_ptr_dtor(&tmp); + } + if (!EG(exception)) { + zend_type_error("strlen(): Argument #1 ($string) must be of type string, %s given", zend_zval_value_name(value)); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } while (0); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_TYPE_CHECK_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + int result = 0; + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { +type_check_resource: + if (opline->extended_value != MAY_BE_RESOURCE + || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { + result = 1; + } + } else if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { + goto type_check_resource; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + result = ((1 << IS_NULL) & opline->extended_value) != 0; + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); + } else { + ZEND_VM_SMART_BRANCH(result, 0); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + uint32_t fetch_type; + zend_class_entry *called_scope, *scope; + USE_OPLINE + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + SAVE_OPLINE(); + zval *op = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_OBJECT) { + zend_type_error("Cannot use \"::class\" on %s", zend_zval_value_name(op)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + fetch_type = opline->op1.num; + scope = EX(func)->op_array.scope; + if (UNEXPECTED(scope == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot use \"%s\" in the global scope", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name); + break; + case ZEND_FETCH_CLASS_PARENT: + if (UNEXPECTED(scope->parent == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, + "Cannot use \"parent\" when current class scope has no parent"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name); + break; + case ZEND_FETCH_CLASS_STATIC: + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + } else { + called_scope = Z_CE(EX(This)); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + div_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + pow_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + compare_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, RT_CONSTANT(opline, opline->op2)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if ((IS_TMP_VAR|IS_VAR) & IS_CV) { + GC_ADDREF(zobj); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CONST == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if (IS_CONST == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_CONST != IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CONST != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + zend_invalid_method_call(object, function_name); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CONST != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +case_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +case_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +case_double: + if (d1 == d2) { + goto case_true; + } else { + goto case_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + + + if (result) { + goto case_true; + } else { + goto case_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, IS_CONST == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); + } + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; + + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_index_array: + if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { + offset = Z_LVAL_P(dim); + } else { + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ht = Z_ARRVAL_P(container); + ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_index_array; + } else { + goto fetch_dim_r_index_slow; + } + } else { +fetch_dim_r_index_slow: + SAVE_OPLINE(); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + +fetch_dim_r_index_undef: + ZVAL_NULL(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + zend_undefined_offset(offset); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; + + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_index_array: + if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { + offset = Z_LVAL_P(dim); + } else { + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ht = Z_ARRVAL_P(container); + ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_index_array; + } else { + goto fetch_dim_r_index_slow; + } + } else { +fetch_dim_r_index_slow: + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + +fetch_dim_r_index_undef: + ZVAL_NULL(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + zend_undefined_offset(offset); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + div_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && (IS_TMP_VAR|IS_VAR) == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if ((IS_TMP_VAR|IS_VAR) & IS_CV) { + GC_ADDREF(zobj); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + zend_invalid_method_call(object, function_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + 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); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +case_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +case_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +case_double: + if (d1 == d2) { + goto case_true; + } else { + goto case_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (result) { + goto case_true; + } else { + goto case_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { + /* avoid exception check */ + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); + } + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + int fetch_type = + (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? + BP_VAR_W : BP_VAR_R; + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + zend_hash_del_ind(target_symbol_table, name); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + bool result; + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else { + name = zval_get_tmp_string(varname, &tmp_name); + } + + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + value = zend_hash_find_ex(target_symbol_table, name, (IS_TMP_VAR|IS_VAR) == IS_CONST); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + if (!value) { + result = (opline->extended_value & ZEND_ISEMPTY); + } else { + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + if (Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + } + result = Z_TYPE_P(value) > IS_NULL; + } else { + result = !i_zend_is_true(value); + } + } + + ZEND_VM_SMART_BRANCH(result, true); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + bool result; + + SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_UNUSED == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); + } + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COUNT_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_long count; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + while (1) { + if (Z_TYPE_P(op1) == IS_ARRAY) { + count = zend_hash_num_elements(Z_ARRVAL_P(op1)); + break; + } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + + /* first, we check if the handler is defined */ + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { + break; + } + if (UNEXPECTED(EG(exception))) { + count = 0; + break; + } + } + + /* if not and the object implements Countable we call its count() method */ + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { + zval retval; + + zend_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); + zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval); + count = zval_get_long(&retval); + zval_ptr_dtor(&retval); + break; + } + + /* If There's no handler and it doesn't implement Countable then emit a TypeError */ + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + count = 0; + zend_type_error("%s(): Argument #1 ($value) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_value_name(op1)); + break; + } + + ZVAL_LONG(EX_VAR(opline->result.var), count); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_array *ht = Z_ARRVAL_P(_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)); + ZVAL_LONG(EX_VAR(opline->result.var), zend_hash_num_elements(ht)); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR) && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + SAVE_OPLINE(); + zend_array_destroy(ht); + if (EG(exception)) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SAVE_OPLINE(); + if (UNEXPECTED(!EX(func)->common.scope)) { + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } else { + zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated"); + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zval *op1; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + while (1) { + if (Z_TYPE_P(op1) == IS_OBJECT) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + break; + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY(result, value); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + div_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = EX_VAR(opline->op2.var); + + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = EX_VAR(opline->op2.var); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if ((IS_TMP_VAR|IS_VAR) & IS_CV) { + GC_ADDREF(zobj); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CV == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = EX_VAR(opline->op2.var); + if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if (IS_CV == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if (IS_CV != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CV != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + zend_invalid_method_call(object, function_name); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CV != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + op2 = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +case_true: + ZEND_VM_SMART_BRANCH_TRUE(); + } else { +case_false: + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +case_double: + if (d1 == d2) { + goto case_true; + } else { + goto case_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto case_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + + + if (result) { + goto case_true; + } else { + goto case_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, IS_CV == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if ((IS_TMP_VAR|IS_VAR) & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || + ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + subject = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + return_value = EX(return_value); + + + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (IS_TMP_VAR == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } + + + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_BY_REF_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + SAVE_OPLINE(); + + return_value = EX(return_value); + + + do { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) || + (IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (!return_value) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + break; + } + + ZVAL_NEW_REF(return_value, retval_ptr); + if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = zend_get_bad_ptr(); + + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + break; + } + } + + if (return_value) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } while (0); + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Copy return value into generator->retval */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + + EG(current_execute_data) = EX(prev_execute_data); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_USER_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg, *param; + + SAVE_OPLINE(); + + arg = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + param = ZEND_CALL_VAR(EX(call), opline->result.var); + if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { + zend_param_must_be_ref(EX(call)->func, opline->op2.num); + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(param, arg); + } else { + ZVAL_COPY(param, arg); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CAST_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + switch (opline->extended_value) { + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(expr)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string(expr)); + break; + default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); + if (IS_TMP_VAR & (IS_VAR|IS_CV)) { + ZVAL_DEREF(expr); + } + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (opline->extended_value == IS_ARRAY) { + zend_cast_zval_to_array(result, expr, IS_TMP_VAR); + } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); + zend_cast_zval_to_object(result, expr, IS_TMP_VAR); + } + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_R_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *result; + + SAVE_OPLINE(); + + array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_TMP_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; + + + ZEND_VM_NEXT_OPCODE(); + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + + + HANDLE_EXCEPTION(); + } + } + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); + } + } else { + properties = zobj->handlers->get_properties(zobj); + } + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_TMP_VAR != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(result) = (uint32_t) -1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_RW_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *array_ref; + + SAVE_OPLINE(); + + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + array_ref = array_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); + } + } else { + array_ref = array_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + } + + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ref = EX_VAR(opline->result.var); + ZVAL_NEW_REF(array_ref, array_ptr); + array_ptr = Z_REFVAL_P(array_ref); + } + if (IS_TMP_VAR == IS_CONST) { + ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); + } else { + SEPARATE_ARRAY(array_ptr); + } + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + + + ZEND_VM_NEXT_OPCODE(); + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + HashTable *properties; + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + + + HANDLE_EXCEPTION(); + } + } + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_OBJ_P(array_ptr)->properties + && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(Z_OBJ_P(array_ptr)->properties); + } + Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } + + properties = Z_OBJPROP_P(array_ptr); + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_END_SILENCE_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting)) + && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) { + EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var)); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_SET_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + bool ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + ret = i_zend_is_true(value); + + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (ret) { + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if (IS_TMP_VAR == IS_VAR && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COALESCE_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_TMP_VAR & IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if ((IS_TMP_VAR & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + if ((IS_TMP_VAR & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_NULL_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val, *result; + + val = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_P(val) > IS_NULL) { + do { + if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + if (Z_TYPE_P(val) <= IS_NULL) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + break; + } + } + ZEND_VM_NEXT_OPCODE(); + } while (0); + } + + result = EX_VAR(opline->result.var); + uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; + if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { + ZVAL_NULL(result); + if (IS_TMP_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) + && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 + ) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { + ZVAL_FALSE(result); + } else { + ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); + ZVAL_TRUE(result); + } + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_SPEC_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *result = EX_VAR(opline->result.var); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(result); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_TMP_VAR == IS_CV) { + ZVAL_COPY_DEREF(result, value); + } else if (IS_TMP_VAR == IS_VAR) { + if (UNEXPECTED(Z_ISREF_P(value))) { + ZVAL_COPY_VALUE(result, Z_REFVAL_P(value)); + if (UNEXPECTED(Z_DELREF_P(value) == 0)) { + efree_size(Z_REF_P(value), sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } else { + ZVAL_COPY_VALUE(result, value); + } + } else { + ZVAL_COPY_VALUE(result, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { + Z_ADDREF_P(result); + } + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_ADD_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; + + /* op1 and result are the same */ + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CONST == IS_CONST) { + var = RT_CONSTANT(opline, opline->op2); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_END_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var, *ret; + uint32_t i; + + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CONST == IS_CONST) { + var = RT_CONSTANT(opline, opline->op2); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + + + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + } + + size_t len = 0; + uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; + for (i = 0; i <= opline->extended_value; i++) { + flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + GC_ADD_FLAGS(Z_STR_P(ret), flags); + + char *target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_EX_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + zval *key = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IN_ARRAY_SPEC_TMP_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; + + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_TMP_VAR == IS_CONST); + if (IS_TMP_VAR & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + ZEND_VM_SMART_BRANCH(result, 0); + } + + if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); + } + SAVE_OPLINE(); + if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); + ZEND_VM_SMART_BRANCH(result, 0); + } else { + zend_string *key; + zval key_tmp; + + if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } + + SAVE_OPLINE(); + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(1, 1); + } + } ZEND_HASH_FOREACH_END(); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(0, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; + + /* op1 and result are the same */ + rope = (zend_string**)EX_VAR(opline->op1.var); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_END_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var, *ret; + uint32_t i; + + rope = (zend_string**)EX_VAR(opline->op1.var); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + } + + size_t len = 0; + uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; + for (i = 0; i <= opline->extended_value; i++) { + flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + GC_ADD_FLAGS(Z_STR_P(ret), flags); + + char *target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_TMP_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_TMP_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_TMP_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (IS_TMP_VAR == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_TMP_VAR != IS_UNUSED) + USE_OPLINE + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); + retval_ref = retval_ptr = EX_VAR(opline->result.var); + } else if (IS_TMP_VAR == IS_VAR) { + if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(retval_ptr); + } + + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); + } else { + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; + } + } + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref:; + ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg_num, arg)); + } + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) { + Z_ADDREF_P(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_UNUSED != IS_UNUSED) { + zval *offset = NULL; + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + zval *key = NULL; + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_TYPE_SPEC_TMP_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_legacy_type(op1); + if (EXPECTED(type)) { + ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); + } else { + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_ADD_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; + + /* op1 and result are the same */ + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CV == IS_CONST) { + var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_END_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var, *ret; + uint32_t i; + + rope = (zend_string**)EX_VAR(opline->op1.var); + if (IS_CV == IS_CONST) { + var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + rope[opline->extended_value] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[opline->extended_value] = zend_string_copy(Z_STR_P(var)); + } else { + rope[opline->extended_value] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[opline->extended_value] = zval_get_string_func(var); + + + if (UNEXPECTED(EG(exception))) { + for (i = 0; i <= opline->extended_value; i++) { + zend_string_release_ex(rope[i], 0); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + } + + size_t len = 0; + uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES; + for (i = 0; i <= opline->extended_value; i++) { + flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]); + len += ZSTR_LEN(rope[i]); + } + ret = EX_VAR(opline->result.var); + ZVAL_STR(ret, zend_string_alloc(len, 0)); + GC_ADD_FLAGS(Z_STR_P(ret), flags); + + char *target = Z_STRVAL_P(ret); + for (i = 0; i <= opline->extended_value; i++) { + memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i])); + target += ZSTR_LEN(rope[i]); + zend_string_release_ex(rope[i], 0); + } + *target = '\0'; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = zend_get_bad_ptr(); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_TMP_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_TMP_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CV != IS_UNUSED) { + zval *offset = EX_VAR(opline->op2.var); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_TMP_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = zend_get_bad_ptr(); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_TMP_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_TMP_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BIND_LEXICAL_SPEC_TMP_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *closure, *var; + + closure = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); + if (opline->extended_value & ZEND_BIND_REF) { + /* By-ref binding */ + var = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); + if (Z_ISREF_P(var)) { + Z_ADDREF_P(var); + } else { + ZVAL_MAKE_REF_EX(var, 2); + } + } else { + var = EX_VAR(opline->op2.var); + if (UNEXPECTED(Z_ISUNDEF_P(var)) && !(opline->extended_value & ZEND_BIND_IMPLICIT)) { + SAVE_OPLINE(); + var = ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + } + + zend_closure_bind_var_ex(closure, + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var); + ZEND_VM_NEXT_OPCODE(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_pre_inc_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + increment_function(var_ptr); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_pre_dec_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + decrement_function(var_ptr); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_post_inc_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + + increment_function(var_ptr); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_increment_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_post_dec_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + + decrement_function(var_ptr); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_DEC_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_decrement_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_VAR_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + return_value = EX(return_value); + + + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (IS_VAR == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } + + + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_BY_REF_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + SAVE_OPLINE(); + + return_value = EX(return_value); + + + do { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR)) || + (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (!return_value) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + break; + } + + ZVAL_NEW_REF(return_value, retval_ptr); + if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); + } else { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + break; + } + } + + if (return_value) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } while (0); + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Copy return value into generator->retval */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + + EG(current_execute_data) = EX(prev_execute_data); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_USER_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg, *param; + + SAVE_OPLINE(); + + arg = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + param = ZEND_CALL_VAR(EX(call), opline->result.var); + if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { + zend_param_must_be_ref(EX(call)->func, opline->op2.num); + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(param, arg); + } else { + ZVAL_COPY(param, arg); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CAST_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + switch (opline->extended_value) { + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(expr)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string(expr)); + break; + default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); + if (IS_VAR & (IS_VAR|IS_CV)) { + ZVAL_DEREF(expr); + } + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (opline->extended_value == IS_ARRAY) { + zend_cast_zval_to_array(result, expr, IS_VAR); + } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); + zend_cast_zval_to_object(result, expr, IS_VAR); + } + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_R_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *result; + + SAVE_OPLINE(); + + array_ptr = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_VAR != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); + } + } else { + properties = zobj->handlers->get_properties(zobj); + } + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_VAR != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(result) = (uint32_t) -1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_RW_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *array_ref; + + SAVE_OPLINE(); + + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + array_ref = array_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); + } + } else { + array_ref = array_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + } + + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ref = EX_VAR(opline->result.var); + ZVAL_NEW_REF(array_ref, array_ptr); + array_ptr = Z_REFVAL_P(array_ref); + } + if (IS_VAR == IS_CONST) { + ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); + } else { + SEPARATE_ARRAY(array_ptr); + } + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + HashTable *properties; + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_OBJ_P(array_ptr)->properties + && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(Z_OBJ_P(array_ptr)->properties); + } + Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } + + properties = Z_OBJPROP_P(array_ptr); + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_FETCH_R_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array; + zval *value; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + + array = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) { + ZEND_VM_TAIL_CALL(zend_fe_fetch_object_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + fe_ht = Z_ARRVAL_P(array); + pos = Z_FE_POS_P(array); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; + } + Z_FE_POS_P(array) = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); + } + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } + } + } + if (EXPECTED(opline->op2_type == IS_CV)) { + zval *variable_ptr = EX_VAR(opline->op2.var); + SAVE_OPLINE(); + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + zval *res = EX_VAR(opline->op2.var); + zend_refcounted *gc = Z_COUNTED_P(value); + + ZVAL_COPY_VALUE_EX(res, value, gc, value_type); + if (Z_TYPE_INFO_REFCOUNTED(value_type)) { + GC_ADDREF(gc); + } + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_FETCH_RW_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array; + zval *value; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + Bucket *p; + + array = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + + ZVAL_DEREF(array); + if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) { + pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array); + fe_ht = Z_ARRVAL_P(array); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1; + if (RETURN_VALUE_USED(opline)) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); + } + } else { + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; + if (RETURN_VALUE_USED(opline)) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } + } + } + } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) { + zend_object_iterator *iter; + + if ((iter = zend_iterator_unwrap(array)) == NULL) { + /* plain object */ + + fe_ht = Z_OBJPROP_P(array); + pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht); + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + goto fe_fetch_w_exit; + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF)) { + if (UNEXPECTED(value_type == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + value_type = Z_TYPE_INFO_P(value); + if (EXPECTED(value_type != IS_UNDEF) + && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) { + if ((value_type & Z_TYPE_MASK) != IS_REFERENCE) { + zend_property_info *prop_info = + zend_get_property_info_for_slot(Z_OBJ_P(array), value); + if (prop_info) { + if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + zend_throw_error(NULL, + "Cannot acquire reference to readonly property %s::$%s", + ZSTR_VAL(prop_info->ce->name), ZSTR_VAL(p->key)); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_NEW_REF(value, value); + ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(value), prop_info); + value_type = IS_REFERENCE_EX; + } + } + } + break; + } + } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0) + || !p->key + || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) { + break; + } + } + p++; + } + EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos; + if (RETURN_VALUE_USED(opline)) { + if (UNEXPECTED(!p->key)) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else if (ZSTR_VAL(p->key)[0]) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } else { + const char *class_name, *prop_name; + size_t prop_name_len; + zend_unmangle_property_name_ex( + p->key, &class_name, &prop_name, &prop_name_len); + ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len); + } + } + } else { + const zend_object_iterator_funcs *funcs = iter->funcs; + if (++iter->index > 0) { + /* This could cause an endless loop if index becomes zero again. + * In case that ever happens we need an additional flag. */ + funcs->move_forward(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(funcs->valid(iter) == FAILURE)) { + /* reached end of iteration */ + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + goto fe_fetch_w_exit; + } + } + value = funcs->get_current_data(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + if (!value) { + /* failure in get_current_data */ + goto fe_fetch_w_exit; + } + if (RETURN_VALUE_USED(opline)) { + if (funcs->get_current_key) { + funcs->get_current_key(iter, EX_VAR(opline->result.var)); + if (UNEXPECTED(EG(exception) != NULL)) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } else { + ZVAL_LONG(EX_VAR(opline->result.var), iter->index); + } + } + value_type = Z_TYPE_INFO_P(value); + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array)); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } +fe_fetch_w_exit: + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + + if (EXPECTED((value_type & Z_TYPE_MASK) != IS_REFERENCE)) { + zend_refcounted *gc = Z_COUNTED_P(value); + zval *ref; + ZVAL_NEW_EMPTY_REF(value); + ref = Z_REFVAL_P(value); + ZVAL_COPY_VALUE_EX(ref, value, gc, value_type); + } + if (EXPECTED(opline->op2_type == IS_CV)) { + zval *variable_ptr = EX_VAR(opline->op2.var); + if (EXPECTED(variable_ptr != value)) { + zend_reference *ref; + + ref = Z_REF_P(value); + GC_ADDREF(ref); + i_zval_ptr_dtor(variable_ptr); + ZVAL_REF(variable_ptr, ref); + } + } else { + Z_ADDREF_P(value); + ZVAL_REF(EX_VAR(opline->op2.var), Z_REF_P(value)); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_SET_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + bool ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + ret = i_zend_is_true(value); + + if (UNEXPECTED(EG(exception))) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (ret) { + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if (IS_VAR == IS_VAR && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COALESCE_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_VAR & IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if ((IS_VAR & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + if ((IS_VAR & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_NULL_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val, *result; + + val = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (Z_TYPE_P(val) > IS_NULL) { + do { + if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + if (Z_TYPE_P(val) <= IS_NULL) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + break; + } + } + ZEND_VM_NEXT_OPCODE(); + } while (0); + } + + result = EX_VAR(opline->result.var); + uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; + if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { + ZVAL_NULL(result); + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) + && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 + ) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { + ZVAL_FALSE(result); + } else { + ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); + ZVAL_TRUE(result); + } + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *result = EX_VAR(opline->result.var); + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(result); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(result, value); + } else if (IS_VAR == IS_VAR) { + if (UNEXPECTED(Z_ISREF_P(value))) { + ZVAL_COPY_VALUE(result, Z_REFVAL_P(value)); + if (UNEXPECTED(Z_DELREF_P(value) == 0)) { + efree_size(Z_REF_P(value), sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } else { + ZVAL_COPY_VALUE(result, value); + } + } else { + ZVAL_COPY_VALUE(result, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { + Z_ADDREF_P(result); + } + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_SIMPLE_SPEC_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if (IS_CONST == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = RT_CONSTANT(opline, opline->op2); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OP_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_VAR, property, IS_CONST, + ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_W_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = RT_CONSTANT(opline, opline->op2); + + if (IS_VAR == IS_VAR + && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT + && UNEXPECTED(!Z_ISREF_P(container)) + ) { + zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); + zend_fetch_dimension_address_LIST_r(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_fetch_dimension_address_W(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = RT_CONSTANT(opline, opline->op2); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_VAR == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_CONST != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_VAR == IS_CONST && + IS_CONST == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_VAR != IS_CONST && + IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_CONST != IS_UNUSED) { + function_name = RT_CONSTANT(opline, opline->op2); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CONST != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr))) { + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + +send_var: + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_REF_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG? + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv, *constant_zv; + zend_string *constant_name; + USE_OPLINE + + SAVE_OPLINE(); + + do { + if (IS_VAR == IS_CONST && IS_CONST == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + } + if (IS_VAR == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value))) { + ce = CACHED_PTR(opline->extended_value); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->extended_value, ce); + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (IS_VAR != IS_CONST + && IS_CONST == IS_CONST + && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + + constant_zv = RT_CONSTANT(opline, opline->op2); + if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { + zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + constant_name = Z_STR_P(constant_zv); + /* Magic 'class' for constant OP2 is caught at compile-time */ + if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + + + ZEND_VM_NEXT_OPCODE(); + } + zv = IS_CONST == IS_CONST + ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) + : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); + + if (EXPECTED(zv != NULL)) { + c = Z_PTR_P(zv); + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + + bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + if (c->ce->type == ZEND_USER_CLASS) { + /* Recursion protection only applied to user constants, GH-18463 */ + CONST_PROTECT_RECURSION(c); + } + zend_deprecated_class_constant(c, constant_name); + if (c->ce->type == ZEND_USER_CLASS) { + CONST_UNPROTECT_RECURSION(c); + } + + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + + value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST && !is_constant_deprecated) { + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } + } else { + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } while (0); + + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_DIM_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); + + do { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +offset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; + } + } +str_index_dim: + ZEND_ASSERT(ht != &EG(symbol_table)); + zend_hash_del(ht, key); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else { + zend_illegal_array_offset_unset(offset); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } + } + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); + } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + zval *key = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IN_ARRAY_SPEC_VAR_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; + + op1 = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_VAR == IS_CONST); + if (IS_VAR & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + ZEND_VM_SMART_BRANCH(result, 0); + } + + if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); + } + SAVE_OPLINE(); + if ((IS_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); + ZEND_VM_SMART_BRANCH(result, 0); + } else { + zend_string *key; + zval key_tmp; + + if ((IS_VAR & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } + + SAVE_OPLINE(); + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(1, 1); + } + } ZEND_HASH_FOREACH_END(); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_SMART_BRANCH(0, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv, *constant_zv; + zend_string *constant_name; + USE_OPLINE + + SAVE_OPLINE(); + + do { + if (IS_VAR == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + } + if (IS_VAR == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value))) { + ce = CACHED_PTR(opline->extended_value); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->extended_value, ce); + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (IS_VAR != IS_CONST + && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + + constant_zv = _get_zval_ptr_tmpvarcv(opline->op2_type, opline->op2, BP_VAR_R EXECUTE_DATA_CC); + if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { + zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + constant_name = Z_STR_P(constant_zv); + /* Magic 'class' for constant OP2 is caught at compile-time */ + if ((IS_TMP_VAR|IS_VAR|IS_CV) != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); + } + zv = (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) + : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); + + if (EXPECTED(zv != NULL)) { + c = Z_PTR_P(zv); + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + + bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + if (c->ce->type == ZEND_USER_CLASS) { + /* Recursion protection only applied to user constants, GH-18463 */ + CONST_PROTECT_RECURSION(c); + } + zend_deprecated_class_constant(c, constant_name); + if (c->ce->type == ZEND_USER_CLASS) { + CONST_UNPROTECT_RECURSION(c); + } + + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + + value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && !is_constant_deprecated) { + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } + } else { + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } while (0); + + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), + (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR + && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT + && UNEXPECTED(!Z_ISREF_P(container)) + ) { + zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); + zend_fetch_dimension_address_LIST_r(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_fetch_dimension_address_W(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_VAR == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_VAR == IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_VAR != IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +offset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; + } + } +str_index_dim: + ZEND_ASSERT(ht != &EG(symbol_table)); + zend_hash_del(ht, key); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else { + zend_illegal_array_offset_unset(offset); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } + } + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); + } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_VAR_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_VAR_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_VAR_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_VAR_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_REF_SPEC_VAR_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *variable_ptr; + zval *value_ptr; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { + + zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); + variable_ptr = &EG(uninitialized_zval); + } else if (IS_VAR == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + + variable_ptr = zend_wrong_assign_to_variable_reference( + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + + if (garbage) { + GC_DTOR(garbage); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = NULL; + if (IS_UNUSED == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if (IS_UNUSED == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = NULL; + if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = NULL; + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = NULL; + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = NULL; + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = NULL; + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = NULL; + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_VAR == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_UNUSED != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_VAR == IS_CONST && + IS_UNUSED == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_VAR != IS_CONST && + IS_UNUSED == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_UNUSED != IS_UNUSED) { + function_name = NULL; + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_UNUSED == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_UNUSED != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (IS_VAR == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_VAR != IS_UNUSED) + USE_OPLINE + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_CONST) { + ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); + retval_ref = retval_ptr = EX_VAR(opline->result.var); + } else if (IS_VAR == IS_VAR) { + if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_VAR == IS_CV) { + ZVAL_DEREF(retval_ptr); + } + + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); + } else { + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; + } + } + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr))) { + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + +send_var: + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } else { + if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var; + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(arg, varptr); + + if (EXPECTED(Z_ISREF_P(varptr) || + ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ZVAL_NEW_REF(arg, arg); + zend_error(E_NOTICE, "Only variables should be passed by reference"); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + +send_var: + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_REF_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_VAR == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG? + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + varptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE(); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NEW_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *result; + zend_function *constructor; + zend_class_entry *ce; + zend_execute_data *call; + + SAVE_OPLINE(); + if (IS_VAR == IS_CONST) { + ce = CACHED_PTR(opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->op2.num, ce); + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { + ZVAL_UNDEF(result); + HANDLE_EXCEPTION(); + } + + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); + if (constructor == NULL) { + /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next + * opcode is DO_FCALL in case EXT instructions are used. */ + if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } + + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + + /* Perform a dummy function call */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, + opline->extended_value, NULL); + } else { + if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { + init_func_run_time_cache(&constructor->op_array); + } + /* We are not handling overloaded classes right now */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, + constructor, + opline->extended_value, + Z_OBJ_P(result)); + Z_ADDREF_P(result); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_UNUSED != IS_UNUSED) { + zval *offset = NULL; + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEPARATE_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + if (UNEXPECTED(Z_ISREF_P(var_ptr))) { + if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { + ZVAL_UNREF(var_ptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + zval *key = NULL; + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MAKE_REF_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1 = EX_VAR(opline->op1.var); + + if (IS_VAR == IS_CV) { + if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_NEW_EMPTY_REF(op1); + Z_SET_REFCOUNT_P(op1, 2); + ZVAL_NULL(Z_REFVAL_P(op1)); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } else { + if (Z_ISREF_P(op1)) { + Z_ADDREF_P(op1); + } else { + ZVAL_MAKE_REF_EX(op1, 2); + } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { + op1 = Z_INDIRECT_P(op1); + if (EXPECTED(!Z_ISREF_P(op1))) { + ZVAL_MAKE_REF_EX(op1, 2); + } else { + GC_ADDREF(Z_REF_P(op1)); + } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } else { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_TYPE_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_legacy_type(op1); + if (EXPECTED(type)) { + ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); + } else { + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; + + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CASE_STRICT_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if (IS_CV == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OP_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_VAR, property, IS_CV, + ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_VAR == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_LIST_W_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + dim = EX_VAR(opline->op2.var); + + if (IS_VAR == IS_VAR + && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT + && UNEXPECTED(!Z_ISREF_P(container)) + ) { + zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); + zend_fetch_dimension_address_LIST_r(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_fetch_dimension_address_W(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_REF_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *variable_ptr; + zval *value_ptr; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + if (IS_VAR == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { + + zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); + variable_ptr = &EG(uninitialized_zval); + } else if (IS_CV == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + + variable_ptr = zend_wrong_assign_to_variable_reference( + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + + if (garbage) { + GC_DTOR(garbage); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_VAR == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_VAR, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_VAR == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_CV != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_VAR == IS_CONST && + IS_CV == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_VAR != IS_CONST && + IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_CV != IS_UNUSED) { + function_name = EX_VAR(opline->op2.var); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CV != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_VAR == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + expr_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_TMP_VAR) { + /* pass */ + } else if (IS_VAR == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_VAR == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CV != IS_UNUSED) { + zval *offset = EX_VAR(opline->op2.var); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_VAR != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_DIM_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = EX_VAR(opline->op2.var); + + do { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +offset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; + } + } +str_index_dim: + ZEND_ASSERT(ht != &EG(symbol_table)); + zend_hash_del(ht, key); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else { + zend_illegal_array_offset_unset(offset); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } + } + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); + } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_VAR == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_VAR_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_VAR == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_VAR == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array; + zval *value, *variable_ptr; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + + array = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + fe_ht = Z_ARRVAL_P(array); + pos = Z_FE_POS_P(array); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; + } + Z_FE_POS_P(array) = pos + 1; + if (0) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); + } + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (0) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } + } + } + + variable_ptr = EX_VAR(opline->op2.var); + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array; + zval *value, *variable_ptr; + uint32_t value_type; + HashTable *fe_ht; + HashPosition pos; + + array = EX_VAR(opline->op1.var); + SAVE_OPLINE(); + fe_ht = Z_ARRVAL_P(array); + pos = Z_FE_POS_P(array); + if (HT_IS_PACKED(fe_ht)) { + value = fe_ht->arPacked + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + pos++; + value++; + } + Z_FE_POS_P(array) = pos + 1; + if (1) { + ZVAL_LONG(EX_VAR(opline->result.var), pos); + } + } else { + Bucket *p; + + p = fe_ht->arData + pos; + while (1) { + if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { + /* reached end of iteration */ + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + pos++; + value = &p->val; + value_type = Z_TYPE_INFO_P(value); + ZEND_ASSERT(value_type != IS_INDIRECT); + if (EXPECTED(value_type != IS_UNDEF)) { + break; + } + p++; + } + Z_FE_POS_P(array) = pos; + if (1) { + if (!p->key) { + ZVAL_LONG(EX_VAR(opline->result.var), p->h); + } else { + ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key); + } + } + } + + variable_ptr = EX_VAR(opline->op2.var); + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CLONE_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *obj; + zend_object *zobj; + zend_class_entry *ce, *scope; + zend_function *clone; + zend_object_clone_obj_t clone_call; + + SAVE_OPLINE(); + obj = &EX(This); + + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ + + 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)) { + obj = Z_REFVAL_P(obj); + if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { + break; + } + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj)); + + + HANDLE_EXCEPTION(); + } + } while (0); + + zobj = Z_OBJ_P(obj); + ce = zobj->ce; + clone = ce->clone; + clone_call = zobj->handlers->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + uint32_t fetch_type; + zend_class_entry *called_scope, *scope; + USE_OPLINE + + if (IS_UNUSED != IS_UNUSED) { + SAVE_OPLINE(); + zval *op = NULL; + if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_OBJECT) { + zend_type_error("Cannot use \"::class\" on %s", zend_zval_value_name(op)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + fetch_type = opline->op1.num; + scope = EX(func)->op_array.scope; + if (UNEXPECTED(scope == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot use \"%s\" in the global scope", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name); + break; + case ZEND_FETCH_CLASS_PARENT: + if (UNEXPECTED(scope->parent == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, + "Cannot use \"parent\" when current class scope has no parent"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name); + break; + case ZEND_FETCH_CLASS_STATIC: + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + } else { + called_scope = Z_CE(EX(This)); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_TAILCALL_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = &EX(This); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, RT_CONSTANT(opline, opline->op2)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_UNUSED & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_UNUSED & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_TAILCALL_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_UNUSED, property, IS_CONST, + ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = &EX(This); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CONST == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_UNUSED == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_UNUSED, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = &EX(This); + property = RT_CONSTANT(opline, opline->op2); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_UNUSED == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_UNUSED, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_INIT_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; + + /* Compiler allocates the necessary number of zval slots to keep the rope */ + rope = (zend_string**)EX_VAR(opline->result.var); + if (IS_CONST == IS_CONST) { + var = RT_CONSTANT(opline, opline->op2); + rope[0] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CONST == IS_CV) { + rope[0] = zend_string_copy(Z_STR_P(var)); + } else { + rope[0] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[0] = zval_get_string_func(var); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *class_name; + USE_OPLINE + + SAVE_OPLINE(); + if (IS_CONST == IS_UNUSED) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->op1.num); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else if (IS_CONST == IS_CONST) { + zend_class_entry *ce = CACHED_PTR(opline->extended_value); + + if (UNEXPECTED(ce == NULL)) { + class_name = RT_CONSTANT(opline, opline->op2); + ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num); + CACHE_PTR(opline->extended_value, ce); + } + Z_CE_P(EX_VAR(opline->result.var)) = ce; + } else { + class_name = RT_CONSTANT(opline, opline->op2); +try_class_name: + if (Z_TYPE_P(class_name) == IS_OBJECT) { + Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); + } else if (Z_TYPE_P(class_name) == IS_STRING) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->op1.num); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) { + class_name = Z_REFVAL_P(class_name); + goto try_class_name; + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Class name must be a valid object or a string"); + } + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = &EX(This); + + if (IS_CONST != IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_UNUSED == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_UNUSED & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CONST != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + zend_invalid_method_call(object, function_name); + + + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CONST != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_UNUSED == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_UNUSED == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_CONST != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_UNUSED == IS_CONST && + IS_CONST == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_UNUSED != IS_CONST && + IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_CONST != IS_UNUSED) { + function_name = RT_CONSTANT(opline, opline->op2); + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CONST != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg_num = zend_get_arg_offset_by_name( + EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1; + if (UNEXPECTED(arg_num == 0)) { + /* Treat this as a by-value argument, and throw an error during SEND. */ + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + ZEND_VM_NEXT_OPCODE(); + } + } else { + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } else { + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } else { + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_constant *c; + + c = CACHED_PTR(opline->extended_value); + if (EXPECTED(c != NULL) && EXPECTED(!IS_SPECIAL_CACHE_VAL(c))) { + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv, *constant_zv; + zend_string *constant_name; + USE_OPLINE + + SAVE_OPLINE(); + + do { + if (IS_UNUSED == IS_CONST && IS_CONST == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + } + if (IS_UNUSED == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value))) { + ce = CACHED_PTR(opline->extended_value); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->extended_value, ce); + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (IS_UNUSED != IS_CONST + && IS_CONST == IS_CONST + && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + + constant_zv = RT_CONSTANT(opline, opline->op2); + if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { + zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + constant_name = Z_STR_P(constant_zv); + /* Magic 'class' for constant OP2 is caught at compile-time */ + if (IS_CONST != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + + + ZEND_VM_NEXT_OPCODE(); + } + zv = IS_CONST == IS_CONST + ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) + : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); + + if (EXPECTED(zv != NULL)) { + c = Z_PTR_P(zv); + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + + bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + if (c->ce->type == ZEND_USER_CLASS) { + /* Recursion protection only applied to user constants, GH-18463 */ + CONST_PROTECT_RECURSION(c); + } + zend_deprecated_class_constant(c, constant_name); + if (c->ce->type == ZEND_USER_CLASS) { + CONST_UNPROTECT_RECURSION(c); + } + + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + + value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST && !is_constant_deprecated) { + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } + } else { + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } while (0); + + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_UNUSED != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = &EX(This); + offset = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = &EX(This); + offset = RT_CONSTANT(opline, opline->op2); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = NULL; + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_UNUSED == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + zval *key = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce, *scope; + zend_class_constant *c; + zval *value, *zv, *constant_zv; + zend_string *constant_name; + USE_OPLINE + + SAVE_OPLINE(); + + do { + if (IS_UNUSED == IS_CONST && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + } + if (IS_UNUSED == IS_CONST) { + if (EXPECTED(CACHED_PTR(opline->extended_value))) { + ce = CACHED_PTR(opline->extended_value); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->extended_value, ce); + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + if (IS_UNUSED != IS_CONST + && (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) { + value = CACHED_PTR(opline->extended_value + sizeof(void*)); + break; + } + + constant_zv = _get_zval_ptr_tmpvarcv(opline->op2_type, opline->op2, BP_VAR_R EXECUTE_DATA_CC); + if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) { + zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + constant_name = Z_STR_P(constant_zv); + /* Magic 'class' for constant OP2 is caught at compile-time */ + if ((IS_TMP_VAR|IS_VAR|IS_CV) != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); + } + zv = (IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST + ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name) + : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name); + + if (EXPECTED(zv != NULL)) { + c = Z_PTR_P(zv); + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { + zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + + bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED; + if (UNEXPECTED(is_constant_deprecated) && !CONST_IS_RECURSIVE(c)) { + if (c->ce->type == ZEND_USER_CLASS) { + /* Recursion protection only applied to user constants, GH-18463 */ + CONST_PROTECT_RECURSION(c); + } + zend_deprecated_class_constant(c, constant_name); + if (c->ce->type == ZEND_USER_CLASS) { + CONST_UNPROTECT_RECURSION(c); + } + + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + + value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if (Z_TYPE_P(value) == IS_CONSTANT_AST) { + if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && !is_constant_deprecated) { + CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value); + } + } else { + zend_throw_error(NULL, "Undefined constant %s::%s", + ZSTR_VAL(ce->name), ZSTR_VAL(constant_name)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + FREE_OP(opline->op2_type, opline->op2.var); + HANDLE_EXCEPTION(); + } + } while (0); + + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value); + + FREE_OP(opline->op2_type, opline->op2.var); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = &EX(This); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_UNUSED & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_UNUSED & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), + (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = &EX(This); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_UNUSED == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = &EX(This); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_UNUSED == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; + + /* Compiler allocates the necessary number of zval slots to keep the rope */ + rope = (zend_string**)EX_VAR(opline->result.var); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + rope[0] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + rope[0] = zend_string_copy(Z_STR_P(var)); + } else { + rope[0] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[0] = zval_get_string_func(var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *class_name; + USE_OPLINE + + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->op1.num); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_class_entry *ce = CACHED_PTR(opline->extended_value); + + if (UNEXPECTED(ce == NULL)) { + class_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num); + CACHE_PTR(opline->extended_value, ce); + } + Z_CE_P(EX_VAR(opline->result.var)) = ce; + } else { + class_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +try_class_name: + if (Z_TYPE_P(class_name) == IS_OBJECT) { + Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); + } else if (Z_TYPE_P(class_name) == IS_STRING) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->op1.num); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) { + class_name = Z_REFVAL_P(class_name); + goto try_class_name; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Class name must be a valid object or a string"); + } + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = &EX(This); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_UNUSED == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_UNUSED & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + zend_invalid_method_call(object, function_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + 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); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_UNUSED == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_UNUSED == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_UNUSED == IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_UNUSED != IS_CONST && + (IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_UNUSED != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = &EX(This); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = &EX(This); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = NULL; + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_UNUSED == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *class_name; + USE_OPLINE + + SAVE_OPLINE(); + if (IS_UNUSED == IS_UNUSED) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->op1.num); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else if (IS_UNUSED == IS_CONST) { + zend_class_entry *ce = CACHED_PTR(opline->extended_value); + + if (UNEXPECTED(ce == NULL)) { + class_name = NULL; + ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num); + CACHE_PTR(opline->extended_value, ce); + } + Z_CE_P(EX_VAR(opline->result.var)) = ce; + } else { + class_name = NULL; +try_class_name: + if (Z_TYPE_P(class_name) == IS_OBJECT) { + Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); + } else if (Z_TYPE_P(class_name) == IS_STRING) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->op1.num); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) { + class_name = Z_REFVAL_P(class_name); + goto try_class_name; + } else { + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Class name must be a valid object or a string"); + } + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_UNUSED == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_UNUSED != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_UNUSED == IS_CONST && + IS_UNUSED == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_UNUSED != IS_CONST && + IS_UNUSED == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_UNUSED != IS_UNUSED) { + function_name = NULL; + if (IS_UNUSED != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_UNUSED == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_UNUSED != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (IS_UNUSED == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_UNUSED != IS_UNUSED) + USE_OPLINE + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = NULL; + + if (IS_UNUSED == IS_CONST) { + ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); + retval_ref = retval_ptr = EX_VAR(opline->result.var); + } else if (IS_UNUSED == IS_VAR) { + if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_UNUSED == IS_CV) { + ZVAL_DEREF(retval_ptr); + } + + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); + } else { + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; + } + } + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + SAVE_OPLINE(); + zend_verify_never_error(EX(func)); + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg_num = zend_get_arg_offset_by_name( + EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1; + if (UNEXPECTED(arg_num == 0)) { + /* Treat this as a by-value argument, and throw an error during SEND. */ + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + ZEND_VM_NEXT_OPCODE(); + } + } else { + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } else { + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } else { + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg_num = zend_get_arg_offset_by_name( + EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1; + if (UNEXPECTED(arg_num == 0)) { + /* Treat this as a by-value argument, and throw an error during SEND. */ + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + ZEND_VM_NEXT_OPCODE(); + } + } else { + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } else { + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } else { + ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_execute_data *call = execute_data->call; + if (EXPECTED(!(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF))) { + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + zend_handle_undef_args(call); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NEW_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *result; + zend_function *constructor; + zend_class_entry *ce; + zend_execute_data *call; + + SAVE_OPLINE(); + if (IS_UNUSED == IS_CONST) { + ce = CACHED_PTR(opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + CACHE_PTR(opline->op2.num, ce); + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { + ZVAL_UNDEF(result); + HANDLE_EXCEPTION(); + } + + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); + if (constructor == NULL) { + /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next + * opcode is DO_FCALL in case EXT instructions are used. */ + if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) { + ZEND_VM_NEXT_OPCODE_EX(1, 2); + } + + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + + /* Perform a dummy function call */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function, + opline->extended_value, NULL); + } else { + if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) { + init_func_run_time_cache(&constructor->op_array); + } + /* We are not handling overloaded classes right now */ + call = zend_vm_stack_push_call_frame( + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS, + constructor, + opline->extended_value, + Z_OBJ_P(result)); + Z_ADDREF_P(result); + } + + call->prev_execute_data = EX(call); + EX(call) = call; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_UNUSED != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = NULL; + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_UNUSED == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + zval *key = NULL; + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) { + zval *result = EX_VAR(opline->result.var); + + ZVAL_OBJ(result, Z_OBJ(EX(This))); + Z_ADDREF_P(result); + ZEND_VM_NEXT_OPCODE(); + } else { + ZEND_VM_TAIL_CALL(zend_this_not_in_object_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* For symbol tables we need to deal with exactly the same problems as for property tables. */ + ZVAL_ARR(EX_VAR(opline->result.var), + zend_proptable_to_symtable(&EG(symbol_table), /* always_duplicate */ 1)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + ZVAL_BOOL(EX_VAR(opline->result.var), + (opline->extended_value & ZEND_ISEMPTY) ^ + (Z_TYPE(EX(This)) == IS_OBJECT)); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (IS_UNUSED == IS_UNUSED) { + SAVE_OPLINE(); + if (UNEXPECTED(!EX(func)->common.scope)) { + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } else { + zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated"); + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zval *op1; + + SAVE_OPLINE(); + op1 = NULL; + while (1) { + if (Z_TYPE_P(op1) == IS_OBJECT) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else { + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + break; + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE(EX(This))->name); + } else if (Z_CE(EX(This))) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name); + } else { + ZEND_ASSERT(!EX(func)->common.scope); + SAVE_OPLINE(); + zend_throw_error(NULL, "get_called_class() must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + ZVAL_LONG(EX_VAR(opline->result.var), EX_NUM_ARGS()); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_array *ht; + uint32_t arg_count, result_size, skip; + + arg_count = EX_NUM_ARGS(); + if (IS_UNUSED == IS_CONST) { + skip = Z_LVAL_P(RT_CONSTANT(opline, opline->op1)); + if (arg_count < skip) { + result_size = 0; + } else { + result_size = arg_count - skip; + } + } else { + skip = 0; + result_size = arg_count; + } + + if (result_size) { + SAVE_OPLINE(); + uint32_t first_extra_arg = EX(func)->op_array.num_args; + + ht = zend_new_array(result_size); + ZVAL_ARR(EX_VAR(opline->result.var), ht); + zend_hash_real_init_packed(ht); + ZEND_HASH_FILL_PACKED(ht) { + zval *p, *q; + uint32_t i = skip; + p = EX_VAR_NUM(i); + if (arg_count > first_extra_arg) { + while (i < first_extra_arg) { + q = p; + if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) { + ZVAL_DEREF(q); + if (Z_OPT_REFCOUNTED_P(q)) { + Z_ADDREF_P(q); + } + ZEND_HASH_FILL_SET(q); + } else { + ZEND_HASH_FILL_SET_NULL(); + } + ZEND_HASH_FILL_NEXT(); + p++; + i++; + } + if (skip < first_extra_arg) { + skip = 0; + } else { + skip -= first_extra_arg; + } + p = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T + skip); + } + while (i < arg_count) { + q = p; + if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) { + ZVAL_DEREF(q); + if (Z_OPT_REFCOUNTED_P(q)) { + Z_ADDREF_P(q); + } + ZEND_HASH_FILL_SET(q); + } else { + ZEND_HASH_FILL_SET_NULL(); + } + ZEND_HASH_FILL_NEXT(); + p++; + i++; + } + } ZEND_HASH_FILL_END(); + ht->nNumOfElements = result_size; + } else { + ZVAL_EMPTY_ARRAY(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE(); +} + +/* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + + zend_closure_from_frame(EX_VAR(opline->result.var), call); + + if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { + OBJ_RELEASE(Z_OBJ(call->This)); + } + + EX(call) = call->prev_execute_data; + + zend_vm_stack_free_call_frame(call); + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + +#if 0 || 0 + if (0 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline); + function(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FRAMELESS_ICALL_0_SPEC_OBSERVER_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + SAVE_OPLINE(); + + zval *result = EX_VAR(opline->result.var); + ZVAL_NULL(result); + +#if 0 || 1 + if (1 && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) { + zend_frameless_observed_call(execute_data); + } else +#endif + { + zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline); + function(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = &EX(This); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_UNUSED & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_UNUSED & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_UNUSED, property, IS_CV, + ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = &EX(This); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CV == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_UNUSED & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_UNUSED == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = &EX(This); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_UNUSED == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_UNUSED, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = &EX(This); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_UNUSED == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_UNUSED, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ROPE_INIT_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string **rope; + zval *var; + + /* Compiler allocates the necessary number of zval slots to keep the rope */ + rope = (zend_string**)EX_VAR(opline->result.var); + if (IS_CV == IS_CONST) { + var = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + rope[0] = Z_STR_P(var); + if (UNEXPECTED(Z_REFCOUNTED_P(var))) { + Z_ADDREF_P(var); + } + } else { + var = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) { + if (IS_CV == IS_CV) { + rope[0] = zend_string_copy(Z_STR_P(var)); + } else { + rope[0] = Z_STR_P(var); + } + } else { + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + rope[0] = zval_get_string_func(var); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *class_name; + USE_OPLINE + + SAVE_OPLINE(); + if (IS_CV == IS_UNUSED) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->op1.num); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else if (IS_CV == IS_CONST) { + zend_class_entry *ce = CACHED_PTR(opline->extended_value); + + if (UNEXPECTED(ce == NULL)) { + class_name = EX_VAR(opline->op2.var); + ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num); + CACHE_PTR(opline->extended_value, ce); + } + Z_CE_P(EX_VAR(opline->result.var)) = ce; + } else { + class_name = EX_VAR(opline->op2.var); +try_class_name: + if (Z_TYPE_P(class_name) == IS_OBJECT) { + Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); + } else if (Z_TYPE_P(class_name) == IS_STRING) { + Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->op1.num); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) { + class_name = Z_REFVAL_P(class_name); + goto try_class_name; + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Class name must be a valid object or a string"); + } + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = &EX(This); + + if (IS_CV != IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_UNUSED == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_UNUSED & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CV != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + zend_invalid_method_call(object, function_name); + + + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CV != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_UNUSED == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zend_class_entry *ce; + uint32_t call_info; + zend_function *fbc; + zend_execute_data *call; + + SAVE_OPLINE(); + + if (IS_UNUSED == IS_CONST) { + /* no function found. try a static method in class */ + ce = CACHED_PTR(opline->result.num); + if (UNEXPECTED(ce == NULL)) { + ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + if (IS_CV != IS_CONST) { + CACHE_PTR(opline->result.num, ce); + } + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op1.num); + if (UNEXPECTED(ce == NULL)) { + + + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + } + + if (IS_UNUSED == IS_CONST && + IS_CV == IS_CONST && + EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) { + /* nothing to do */ + } else if (IS_UNUSED != IS_CONST && + IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == ce)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else if (IS_CV != IS_UNUSED) { + function_name = EX_VAR(opline->op2.var); + if (IS_CV != IS_CONST) { + if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + HANDLE_EXCEPTION(); + } while (0); + } + } + + if (ce->get_static_method) { + fbc = ce->get_static_method(ce, Z_STR_P(function_name)); + } else { + fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + } + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(ce, Z_STR_P(function_name)); + } + + + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) { + CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc); + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + if (IS_CV != IS_CONST) { + + + } + } else { + if (UNEXPECTED(ce->constructor == NULL)) { + zend_throw_error(NULL, "Cannot call constructor"); + HANDLE_EXCEPTION(); + } + if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { + zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name)); + HANDLE_EXCEPTION(); + } + fbc = ce->constructor; + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) { + if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) { + ce = (zend_class_entry*)Z_OBJ(EX(This)); + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + } else { + zend_non_static_method_call(fbc); + HANDLE_EXCEPTION(); + } + } else { + /* previous opcode is ZEND_FETCH_CLASS */ + if (IS_UNUSED == IS_UNUSED + && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT || + (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) { + if (Z_TYPE(EX(This)) == IS_OBJECT) { + ce = Z_OBJCE(EX(This)); + } else { + ce = Z_CE(EX(This)); + } + } + call_info = ZEND_CALL_NESTED_FUNCTION; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, ce); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_UNUSED != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = &EX(This); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_UNUSED == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = &EX(This); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + if (IS_UNUSED == IS_CONST || + (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_UNUSED_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = NULL; + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_UNUSED == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_UNUSED == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_NOT_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + + val = EX_VAR(opline->op1.var); + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); + ZVAL_TRUE(EX_VAR(opline->result.var)); + if (IS_CV == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } else { + SAVE_OPLINE(); + ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_pre_inc_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + increment_function(var_ptr); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_inc_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_pre_dec_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + decrement_function(var_ptr); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_pre_dec_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_post_inc_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + + increment_function(var_ptr); + } while (0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_increment_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_post_inc_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_post_dec_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(var_ptr); + } + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + + decrement_function(var_ptr); + } while (0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_DEC_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_decrement_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); + } + + ZEND_VM_TAIL_CALL(zend_post_dec_helper_SPEC_CV_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ECHO_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *z; + + SAVE_OPLINE(); + z = EX_VAR(opline->op1.var); + + if (Z_TYPE_P(z) == IS_STRING) { + zend_string *str = Z_STR_P(z); + + if (ZSTR_LEN(str) != 0) { + zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); + } + } else { + zend_string *str = zval_get_string_func(z); + + if (ZSTR_LEN(str) != 0) { + zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_string_release_ex(str, 0); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPZ_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + uint8_t op1_type; + + val = EX_VAR(opline->op1.var); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + SAVE_OPLINE(); + op1_type = IS_CV; + if (i_zend_is_true(val)) { + opline++; + } else { + opline = OP_JMP_ADDR(opline, opline->op2); + } + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } + ZEND_VM_JMP(opline); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPNZ_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + uint8_t op1_type; + + val = EX_VAR(opline->op1.var); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + op1_type = IS_CV; + if (i_zend_is_true(val)) { + opline = OP_JMP_ADDR(opline, opline->op2); + } else { + opline++; + } + if (op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(val); + } + ZEND_VM_JMP(opline); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPZ_EX_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + bool ret; + + val = EX_VAR(opline->op1.var); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_NEXT_OPCODE(); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + SAVE_OPLINE(); + ret = i_zend_is_true(val); + + + if (ret) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline++; + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline = OP_JMP_ADDR(opline, opline->op2); + } + ZEND_VM_JMP(opline); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMPNZ_EX_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + bool ret; + + val = EX_VAR(opline->op1.var); + + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + ret = i_zend_is_true(val); + + + if (ret) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + opline = OP_JMP_ADDR(opline, opline->op2); + } else { + ZVAL_FALSE(EX_VAR(opline->result.var)); + opline++; + } + ZEND_VM_JMP(opline); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + retval_ptr = EX_VAR(opline->op1.var); + return_value = EX(return_value); + + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (IS_CV == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } + + + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_RETURN_BY_REF_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + SAVE_OPLINE(); + + return_value = EX(return_value); + + + do { + if ((IS_CV & (IS_CONST|IS_TMP_VAR)) || + (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { + /* Not supposed to happen, but we'll allow it */ + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + + retval_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (!return_value) { + + + } else { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + break; + } + + ZVAL_NEW_REF(return_value, retval_ptr); + if (IS_CV == IS_CONST) { + Z_TRY_ADDREF_P(retval_ptr); + } + } + break; + } + + retval_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + + if (IS_CV == IS_VAR) { + ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) { + zend_error(E_NOTICE, "Only variable references should be returned by reference"); + if (return_value) { + ZVAL_NEW_REF(return_value, retval_ptr); + } else { + + + } + break; + } + } + + if (return_value) { + if (Z_ISREF_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } else { + ZVAL_MAKE_REF_EX(retval_ptr, 2); + } + ZVAL_REF(return_value, Z_REF_P(retval_ptr)); + } + + + } while (0); + + + + + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GENERATOR_RETURN_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *retval; + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + retval = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + /* Copy return value into generator->retval */ + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(&generator->retval, retval); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) { + Z_ADDREF(generator->retval); + } + } + } else if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(&generator->retval, retval); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_refcounted *ref = Z_COUNTED_P(retval); + + retval = Z_REFVAL_P(retval); + ZVAL_COPY_VALUE(&generator->retval, retval); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval)) { + Z_ADDREF_P(retval); + } + } else { + ZVAL_COPY_VALUE(&generator->retval, retval); + } + } + + + EG(current_execute_data) = EX(prev_execute_data); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_THROW_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + SAVE_OPLINE(); + value = EX_VAR(opline->op1.var); + + do { + if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) { + break; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Can only throw objects"); + + + HANDLE_EXCEPTION(); + } + } while (0); + + zend_exception_save(); + Z_TRY_ADDREF_P(value); + zend_throw_exception_object(value); + zend_exception_restore(); + + + HANDLE_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_USER_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *arg, *param; + + SAVE_OPLINE(); + + arg = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + param = ZEND_CALL_VAR(EX(call), opline->result.var); + if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) { + zend_param_must_be_ref(EX(call)->func, opline->op2.num); + Z_TRY_ADDREF_P(arg); + ZVAL_NEW_REF(param, arg); + } else { + ZVAL_COPY(param, arg); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val; + + val = EX_VAR(opline->op1.var); + if (Z_TYPE_INFO_P(val) == IS_TRUE) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); + ZVAL_FALSE(EX_VAR(opline->result.var)); + if (IS_CV == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + } else { + SAVE_OPLINE(); + ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CLONE_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *obj; + zend_object *zobj; + zend_class_entry *ce, *scope; + zend_function *clone; + zend_object_clone_obj_t clone_call; + + SAVE_OPLINE(); + obj = EX_VAR(opline->op1.var); + + /* ZEND_CLONE also exists as the clone() function and both implementations must be kept in sync. + * The OPcode intentionally does not support a clone-with property list to keep it simple. */ + + 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)) { + obj = Z_REFVAL_P(obj); + if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) { + break; + } + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + zend_type_error("clone(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(obj)); + + + HANDLE_EXCEPTION(); + } + } while (0); + + zobj = Z_OBJ_P(obj); + ce = zobj->ce; + clone = ce->clone; + clone_call = zobj->handlers->clone_obj; + if (UNEXPECTED(clone_call == NULL)) { + zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name)); + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) { + scope = EX(func)->op_array.scope; + ZEND_ASSERT(!(clone->common.fn_flags & ZEND_ACC_PUBLIC)); + if (!zend_check_method_accessible(clone, scope)) { + zend_bad_method_call(clone, clone->common.function_name, scope); + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CAST_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + zval *result = EX_VAR(opline->result.var); + + SAVE_OPLINE(); + expr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + switch (opline->extended_value) { + case IS_LONG: + ZVAL_LONG(result, zval_get_long(expr)); + break; + case IS_DOUBLE: + ZVAL_DOUBLE(result, zval_get_double(expr)); + break; + case IS_STRING: + ZVAL_STR(result, zval_get_string(expr)); + break; + default: + ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead"); + if (IS_CV & (IS_VAR|IS_CV)) { + ZVAL_DEREF(expr); + } + /* If value is already of correct type, return it directly */ + if (Z_TYPE_P(expr) == opline->extended_value) { + ZVAL_COPY_VALUE(result, expr); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_CV != IS_TMP_VAR) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (opline->extended_value == IS_ARRAY) { + zend_cast_zval_to_array(result, expr, IS_CV); + } else { + ZEND_ASSERT(opline->extended_value == IS_OBJECT); + zend_cast_zval_to_object(result, expr, IS_CV); + } + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INCLUDE_OR_EVAL_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_op_array *new_op_array; + zval *inc_filename; + + SAVE_OPLINE(); + inc_filename = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + new_op_array = zend_include_or_eval(inc_filename, opline->extended_value); + if (UNEXPECTED(EG(exception) != NULL)) { + + + if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) { + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (new_op_array == ZEND_FAKE_OP_ARRAY) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_TRUE(EX_VAR(opline->result.var)); + } + } else if (UNEXPECTED(new_op_array == NULL)) { + if (RETURN_VALUE_USED(opline)) { + ZVAL_FALSE(EX_VAR(opline->result.var)); + } + } else if (new_op_array->last == 1 + && new_op_array->opcodes[0].opcode == ZEND_RETURN + && 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; + + ZVAL_COPY(EX_VAR(opline->result.var), RT_CONSTANT(op, op->op1)); + } + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + } else { + zval *return_value = NULL; + zend_execute_data *call; + if (RETURN_VALUE_USED(opline)) { + return_value = EX_VAR(opline->result.var); + } + + 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, + (zend_function*)new_op_array, 0, + Z_PTR(EX(This))); + + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { + call->symbol_table = EX(symbol_table); + } else { + call->symbol_table = zend_rebuild_symbol_table(); + } + + call->prev_execute_data = execute_data; + i_init_code_execute_data(call, new_op_array, return_value); + + + if (EXPECTED(zend_execute_ex == execute_ex)) { + + + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + zend_vm_stack_free_call_frame(call); + } + + zend_destroy_static_vars(new_op_array); + destroy_op_array(new_op_array); + efree_size(new_op_array, sizeof(zend_op_array)); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_rethrow_exception(execute_data); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_R_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *result; + + SAVE_OPLINE(); + + array_ptr = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CV != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(array_ptr); + } + Z_FE_POS_P(result) = 0; + + + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + + + HANDLE_EXCEPTION(); + } + } + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); + } + } else { + properties = zobj->handlers->get_properties(zobj); + } + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (IS_CV != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(result) = (uint32_t) -1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FE_RESET_RW_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *array_ptr, *array_ref; + + SAVE_OPLINE(); + + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(array_ref)) { + array_ptr = Z_REFVAL_P(array_ref); + } + } else { + array_ref = array_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + } + + if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) { + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ref = EX_VAR(opline->result.var); + ZVAL_NEW_REF(array_ref, array_ptr); + array_ptr = Z_REFVAL_P(array_ref); + } + if (IS_CV == IS_CONST) { + ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr))); + } else { + SEPARATE_ARRAY(array_ptr); + } + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0); + + + ZEND_VM_NEXT_OPCODE(); + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { + if (!Z_OBJCE_P(array_ptr)->get_iterator) { + zend_object *zobj = Z_OBJ_P(array_ptr); + HashTable *properties; + if (UNEXPECTED(zend_object_is_lazy(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (UNEXPECTED(EG(exception))) { + UNDEF_RESULT(); + + + HANDLE_EXCEPTION(); + } + } + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + if (array_ptr == array_ref) { + ZVAL_NEW_REF(array_ref, array_ref); + array_ptr = Z_REFVAL_P(array_ref); + } + Z_ADDREF_P(array_ref); + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref); + } else { + array_ptr = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(array_ptr, array_ref); + } + if (Z_OBJ_P(array_ptr)->properties + && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(Z_OBJ_P(array_ptr)->properties); + } + Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } + + properties = Z_OBJPROP_P(array_ptr); + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } else if (is_empty) { + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } + } else { + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; + + + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_SET_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + bool ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + ret = i_zend_is_true(value); + + if (UNEXPECTED(EG(exception))) { + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + if (ret) { + zval *result = EX_VAR(opline->result.var); + + ZVAL_COPY_VALUE(result, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if (IS_CV == IS_VAR && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COALESCE_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zend_reference *ref = NULL; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_CV & IS_VAR) { + ref = Z_REF_P(value); + } + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if ((IS_CV & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + if ((IS_CV & IS_VAR) && ref) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_JMP_NULL_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *val, *result; + + val = EX_VAR(opline->op1.var); + + if (Z_TYPE_P(val) > IS_NULL) { + do { + if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + if (Z_TYPE_P(val) <= IS_NULL) { + + + break; + } + } + ZEND_VM_NEXT_OPCODE(); + } while (0); + } + + result = EX_VAR(opline->result.var); + uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK; + if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) { + ZVAL_NULL(result); + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF) + && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0 + ) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) { + ZVAL_FALSE(result); + } else { + ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY); + ZVAL_TRUE(result); + } + + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_QM_ASSIGN_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *result = EX_VAR(opline->result.var); + + value = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(result); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(result, value); + } else if (IS_CV == IS_VAR) { + if (UNEXPECTED(Z_ISREF_P(value))) { + ZVAL_COPY_VALUE(result, Z_REFVAL_P(value)); + if (UNEXPECTED(Z_DELREF_P(value) == 0)) { + efree_size(Z_REF_P(value), sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } else { + ZVAL_COPY_VALUE(result, value); + } + } else { + ZVAL_COPY_VALUE(result, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) { + Z_ADDREF_P(result); + } + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_FROM_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + zval *val; + + SAVE_OPLINE(); + val = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator"); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + +yield_from_try_again: + if (Z_TYPE_P(val) == IS_ARRAY) { + ZVAL_COPY_VALUE(&generator->values, val); + if (Z_OPT_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); + } + Z_FE_POS(generator->values) = 0; + + + } else if (IS_CV != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) { + zend_class_entry *ce = Z_OBJCE_P(val); + if (ce == zend_ce_generator) { + zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val); + + Z_ADDREF_P(val); + + + if (UNEXPECTED(new_gen->execute_data == NULL)) { + zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else if (Z_ISUNDEF(new_gen->retval)) { + if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) { + zend_throw_error(NULL, "Impossible to yield from the Generator being currently run"); + zval_ptr_dtor(val); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } else { + zend_generator_yield_from(generator, new_gen); + } + } else { + if (RETURN_VALUE_USED(opline)) { + ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zend_object_iterator *iter = ce->get_iterator(ce, val, 0); + + + if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) { + if (!EG(exception)) { + zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)); + } + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + iter->index = 0; + if (iter->funcs->rewind) { + iter->funcs->rewind(iter); + if (UNEXPECTED(EG(exception) != NULL)) { + OBJ_RELEASE(&iter->std); + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + } + + ZVAL_OBJ(&generator->values, &iter->std); + } + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) { + val = Z_REFVAL_P(val); + goto yield_from_try_again; + } else { + zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables"); + + + UNDEF_RESULT(); + HANDLE_EXCEPTION(); + } + + /* This is the default return value + * when the expression is a Generator, it will be overwritten in zend_generator_resume() */ + if (RETURN_VALUE_USED(opline)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_STRLEN_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = EX_VAR(opline->op1.var); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(value); + } + ZEND_VM_NEXT_OPCODE(); + } else { + bool strict; + + if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) { + value = Z_REFVAL_P(value); + if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value)); + + + ZEND_VM_NEXT_OPCODE(); + } + } + + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + value = ZVAL_UNDEFINED_OP1(); + } + strict = EX_USES_STRICT_TYPES(); + do { + if (EXPECTED(!strict)) { + zend_string *str; + zval tmp; + + if (UNEXPECTED(Z_TYPE_P(value) == IS_NULL)) { + zend_error(E_DEPRECATED, + "strlen(): Passing null to parameter #1 ($string) of type string is deprecated"); + ZVAL_LONG(EX_VAR(opline->result.var), 0); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + break; + } + + ZVAL_COPY(&tmp, value); + if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); + zval_ptr_dtor(&tmp); + break; + } + zval_ptr_dtor(&tmp); + } + if (!EG(exception)) { + zend_type_error("strlen(): Argument #1 ($string) must be of type string, %s given", zend_zval_value_name(value)); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } while (0); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_TYPE_CHECK_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + int result = 0; + + value = EX_VAR(opline->op1.var); + if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { +type_check_resource: + if (opline->extended_value != MAY_BE_RESOURCE + || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { + result = 1; + } + } else if ((IS_CV & (IS_CV|IS_VAR)) && Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { + goto type_check_resource; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + result = ((1 << IS_NULL) & opline->extended_value) != 0; + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + + + ZEND_VM_SMART_BRANCH(result, 1); + } else { + ZEND_VM_SMART_BRANCH(result, 0); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_CLASS_NAME_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + uint32_t fetch_type; + zend_class_entry *called_scope, *scope; + USE_OPLINE + + if (IS_CV != IS_UNUSED) { + SAVE_OPLINE(); + zval *op = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) { + ZVAL_DEREF(op); + if (Z_TYPE_P(op) != IS_OBJECT) { + zend_type_error("Cannot use \"::class\" on %s", zend_zval_value_name(op)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + + + HANDLE_EXCEPTION(); + } + } + + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + fetch_type = opline->op1.num; + scope = EX(func)->op_array.scope; + if (UNEXPECTED(scope == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot use \"%s\" in the global scope", + fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : + fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + + switch (fetch_type) { + case ZEND_FETCH_CLASS_SELF: + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name); + break; + case ZEND_FETCH_CLASS_PARENT: + if (UNEXPECTED(scope->parent == NULL)) { + SAVE_OPLINE(); + zend_throw_error(NULL, + "Cannot use \"parent\" when current class scope has no parent"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name); + break; + case ZEND_FETCH_CLASS_STATIC: + if (Z_TYPE(EX(This)) == IS_OBJECT) { + called_scope = Z_OBJCE(EX(This)); + } else { + called_scope = Z_CE(EX(This)); + } + ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BIND_STATIC_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + HashTable *ht; + zval *value; + zval *variable_ptr; + + variable_ptr = EX_VAR(opline->op1.var); + + SAVE_OPLINE(); + + ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr); + if (!ht) { + ht = zend_array_dup(EX(func)->op_array.static_variables); + ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht); + } + ZEND_ASSERT(GC_REFCOUNT(ht) == 1); + + value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT))); + + if (opline->extended_value & ZEND_BIND_REF) { + if (UNEXPECTED(!Z_ISREF_P(value))) { + zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference)); + GC_SET_REFCOUNT(ref, 2); + GC_TYPE_INFO(ref) = GC_REFERENCE; + if (opline->op2_type == IS_UNUSED) { + ZVAL_COPY_VALUE(&ref->val, value); + } else { + ZEND_ASSERT(!Z_REFCOUNTED_P(value)); + ZVAL_COPY(&ref->val, get_zval_ptr_deref(opline->op2_type, opline->op2, BP_VAR_R)); + FREE_OP(opline->op2_type, opline->op2.var); + } + ref->sources.ptr = NULL; + Z_REF_P(value) = ref; + Z_TYPE_INFO_P(value) = IS_REFERENCE_EX; + i_zval_ptr_dtor(variable_ptr); + ZVAL_REF(variable_ptr, ref); + } else { + Z_ADDREF_P(value); + i_zval_ptr_dtor(variable_ptr); + ZVAL_REF(variable_ptr, Z_REF_P(value)); + if (opline->op2_type != IS_UNUSED) { + FREE_OP(opline->op2_type, opline->op2.var); + } + } + } else { + i_zval_ptr_dtor(variable_ptr); + ZVAL_COPY(variable_ptr, value); + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + HashTable *ht; + zval *value; + zval *variable_ptr; + + variable_ptr = EX_VAR(opline->op1.var); + + ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr); + if (!ht) { + ZEND_VM_NEXT_OPCODE(); + } + ZEND_ASSERT(GC_REFCOUNT(ht) == 1); + + value = (zval*)((char*)ht->arData + opline->extended_value); + if (Z_TYPE_P(value) == IS_NULL) { + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + zval_ptr_dtor(variable_ptr); + ZEND_ASSERT(Z_TYPE_P(value) == IS_REFERENCE); + Z_ADDREF_P(value); + ZVAL_REF(variable_ptr, Z_REF_P(value)); + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 1); + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + Z_LVAL_P(var_ptr)++; + if (UNEXPECTED(0)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + Z_LVAL_P(var_ptr)++; + if (UNEXPECTED(1)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + fast_long_increment_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + fast_long_increment_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + Z_LVAL_P(var_ptr)--; + if (UNEXPECTED(0)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + Z_LVAL_P(var_ptr)--; + if (UNEXPECTED(1)) { + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(0)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + Z_LVAL_P(var_ptr)++; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_LONG_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_increment_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + Z_LVAL_P(var_ptr)--; + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_DEC_LONG_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + + var_ptr = EX_VAR(opline->op1.var); + ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); + fast_long_decrement_function(var_ptr); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_SIMPLE_SPEC_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + varptr = EX_VAR(opline->op1.var); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_CV == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + div_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + pow_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + + if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_not_identical_function(op1, op2); + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CV == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CV == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CV == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CV == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CV == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if (1 && IS_CV == IS_CONST && IS_CONST == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + compare_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_XOR_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = RT_CONSTANT(opline, opline->op2); + boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if (IS_CONST == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = RT_CONSTANT(opline, opline->op2); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OP_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CV != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_W(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_RW(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_read_IS(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CONST == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_UNSET(container, RT_CONSTANT(opline, opline->op2), IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_CONST_TAILCALL_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, RT_CONSTANT(opline, opline->op2)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_CV & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_CV & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CV_CONST_TAILCALL_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_CV, property, IS_CONST, + ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CONST == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CONST == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, RT_CONSTANT(opline, opline->op2) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CONST == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + } else { + name = zval_try_get_tmp_string(RT_CONSTANT(opline, opline->op2), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CONST == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CONST == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = RT_CONSTANT(opline, opline->op2); + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = RT_CONSTANT(opline, opline->op2); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = RT_CONSTANT(opline, opline->op2); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CONST != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = RT_CONSTANT(opline, opline->op2); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_CV == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_CV, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = RT_CONSTANT(opline, opline->op2); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_CV == IS_UNUSED) { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CONST == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_CV, property, IS_CONST, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST || IS_CONST == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CONST != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CV == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if (IS_CONST == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if (IS_CV != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if (IS_CONST != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CONST != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = EX_VAR(opline->op1.var); + + if (IS_CONST != IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + if (IS_CONST != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_CV == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CV & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CONST != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + zend_invalid_method_call(object, function_name); + + + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CONST == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CONST == IS_CONST) { + function_name = RT_CONSTANT(opline, opline->op2); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CONST == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CONST != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_CV == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_REF_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_CONST == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_CONST == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + + ZEND_VM_NEXT_OPCODE(); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (IS_CV == IS_TMP_VAR) { + /* pass */ + } else if (IS_CV == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CV == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CONST != IS_UNUSED) { + zval *offset = RT_CONSTANT(opline, opline->op2); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CV != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_DIM_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = RT_CONSTANT(opline, opline->op2); + + do { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +offset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; + } + } +str_index_dim: + ZEND_ASSERT(ht != &EG(symbol_table)); + zend_hash_del(ht, key); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else { + zend_illegal_array_offset_unset(offset); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); + } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = RT_CONSTANT(opline, opline->op2); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, IS_CONST == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if (IS_CV & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if (IS_CONST == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + offset = RT_CONSTANT(opline, opline->op2); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CONST == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CONST == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = EX_VAR(opline->op1.var); + subject = RT_CONSTANT(opline, opline->op2); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INSTANCEOF_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + bool result; + + SAVE_OPLINE(); + expr = EX_VAR(opline->op1.var); + +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_CONST == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); + } + } + } else if (IS_CONST == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CV == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + zval *key = RT_CONSTANT(opline, opline->op2); + if ((IS_CONST & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BIND_GLOBAL_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_string *varname; + zval *value; + zval *variable_ptr; + uintptr_t idx; + zend_reference *ref; + + ZEND_VM_REPEATABLE_OPCODE + + varname = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + + /* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ + idx = (uintptr_t)CACHED_PTR(opline->extended_value) - 1; + if (EXPECTED(idx < EG(symbol_table).nNumUsed * sizeof(Bucket))) { + 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)))) { + + value = (zval*)p; /* value = &p->val; */ + goto check_indirect; + } + } + + value = zend_hash_find_known_hash(&EG(symbol_table), varname); + if (UNEXPECTED(value == NULL)) { + value = zend_hash_add_new(&EG(symbol_table), varname, &EG(uninitialized_zval)); + idx = (char*)value - (char*)EG(symbol_table).arData; + /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ + CACHE_PTR(opline->extended_value, (void*)(idx + 1)); + } else { + idx = (char*)value - (char*)EG(symbol_table).arData; + /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */ + CACHE_PTR(opline->extended_value, (void*)(idx + 1)); +check_indirect: + /* GLOBAL variable may be an INDIRECT pointer to CV */ + if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) { + value = Z_INDIRECT_P(value); + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + ZVAL_NULL(value); + } + } + } + + if (UNEXPECTED(!Z_ISREF_P(value))) { + ZVAL_MAKE_REF_EX(value, 2); + ref = Z_REF_P(value); + } else { + ref = Z_REF_P(value); + GC_ADDREF(ref); + } + + variable_ptr = EX_VAR(opline->op1.var); + + if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { + zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); + + ZVAL_REF(variable_ptr, ref); + SAVE_OPLINE(); + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + if (UNEXPECTED(EG(exception))) { + ZVAL_NULL(variable_ptr); + HANDLE_EXCEPTION(); + } + } else { + gc_check_possible_root(garbage); + } + } else { + ZVAL_REF(variable_ptr, ref); + } + + ZEND_VM_REPEAT_OPCODE(ZEND_BIND_GLOBAL); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IN_ARRAY_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2)); + zval *result; + + op1 = EX_VAR(opline->op1.var); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find_ex(ht, Z_STR_P(op1), IS_CV == IS_CONST); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + ZEND_VM_SMART_BRANCH(result, 0); + } + + if (opline->extended_value) { + if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + ZEND_VM_SMART_BRANCH(result, 0); + } + SAVE_OPLINE(); + if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + + + ZEND_VM_SMART_BRANCH(result, 0); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + result = zend_hash_index_find(ht, Z_LVAL_P(op1)); + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + } else if (Z_TYPE_P(op1) <= IS_FALSE) { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC()); + ZEND_VM_SMART_BRANCH(result, 0); + } else { + zend_string *key; + zval key_tmp; + + if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + result = zend_hash_find(ht, Z_STR_P(op1)); + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } + + SAVE_OPLINE(); + ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) { + ZVAL_STR(&key_tmp, key); + if (zend_compare(op1, &key_tmp) == 0) { + + + ZEND_VM_SMART_BRANCH(1, 1); + } + } ZEND_HASH_FOREACH_END(); + } + + + ZEND_VM_SMART_BRANCH(0, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */ + /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */ + /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = RT_CONSTANT(opline, opline->op2); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(!result, 0); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; + + container = EX_VAR(opline->op1.var); + dim = RT_CONSTANT(opline, opline->op2); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_index_array: + if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { + offset = Z_LVAL_P(dim); + } else { + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ht = Z_ARRVAL_P(container); + ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_index_array; + } else { + goto fetch_dim_r_index_slow; + } + } else { +fetch_dim_r_index_slow: + SAVE_OPLINE(); + if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + +fetch_dim_r_index_undef: + ZVAL_NULL(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + zend_undefined_offset(offset); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + zend_long offset; + HashTable *ht; + + container = EX_VAR(opline->op1.var); + dim = EX_VAR(opline->op2.var); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_index_array: + if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { + offset = Z_LVAL_P(dim); + } else { + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ht = Z_ARRVAL_P(container); + ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + SAVE_OPLINE(); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZEND_VM_NEXT_OPCODE(); + } + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_index_array; + } else { + goto fetch_dim_r_index_slow; + } + } else { +fetch_dim_r_index_slow: + SAVE_OPLINE(); + if ((IS_TMP_VAR|IS_VAR|IS_CV) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + +fetch_dim_r_index_undef: + ZVAL_NULL(EX_VAR(opline->result.var)); + SAVE_OPLINE(); + zend_undefined_offset(offset); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + div_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (1 && IS_CV == IS_CONST && (IS_TMP_VAR|IS_VAR) == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_XOR_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (IS_CV != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_W(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_RW(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_read_IS(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_UNSET(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), (IS_TMP_VAR|IS_VAR) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_CV & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_CV & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), + (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_CV == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_CV == IS_UNUSED) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_CV, property, (IS_TMP_VAR|IS_VAR), value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = EX_VAR(opline->op1.var); + op2 = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST || (IS_TMP_VAR|IS_VAR) == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CV == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if (IS_CV != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = EX_VAR(opline->op1.var); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_CV == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CV & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + HANDLE_EXCEPTION(); + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + function_name = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + } + zend_invalid_method_call(object, function_name); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + 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); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_CV == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (IS_CV == IS_TMP_VAR) { + /* pass */ + } else if (IS_CV == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CV == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CV != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_DIM_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +offset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; + } + } +str_index_dim: + ZEND_ASSERT(ht != &EG(symbol_table)); + zend_hash_del(ht, key); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else { + zend_illegal_array_offset_unset(offset); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); + } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, (IS_TMP_VAR|IS_VAR) == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if (IS_CV & (IS_CONST|IS_CV)) { + /* avoid exception check */ + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = EX_VAR(opline->op1.var); + subject = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_TMPVAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CV == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) { + zval *key = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if (((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_CV_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_CV_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_REF_SPEC_CV_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *variable_ptr; + zval *value_ptr; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { + + zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); + variable_ptr = &EG(uninitialized_zval); + } else if (IS_VAR == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + + variable_ptr = zend_wrong_assign_to_variable_reference( + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + + if (garbage) { + GC_DTOR(garbage); + } + + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INSTANCEOF_SPEC_CV_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + bool result; + + SAVE_OPLINE(); + expr = EX_VAR(opline->op1.var); + +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_VAR == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); + } + } + } else if (IS_VAR == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = NULL; + if (IS_UNUSED == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if (IS_UNUSED == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = NULL; + if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = NULL; + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type); +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_R_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_R)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_W_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_W)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_RW_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_RW)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + int fetch_type = + (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? + BP_VAR_W : BP_VAR_R; + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX fetch_type)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_UNSET_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_UNSET)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_IS_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX BP_VAR_IS)); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_W(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_RW(container, NULL, IS_UNUSED OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_UNUSED == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = NULL; + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = NULL; + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = NULL; + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_UNUSED == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = NULL; + if (IS_UNUSED == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_UNUSED == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = NULL; + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = NULL; + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = NULL; +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_UNUSED != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (IS_CV == IS_UNUSED) { + SAVE_OPLINE(); + zend_verify_missing_return_type(EX(func)); + HANDLE_EXCEPTION(); + } else { +/* prevents "undefined variable opline" errors */ +#if 0 || (IS_CV != IS_UNUSED) + USE_OPLINE + zval *retval_ref, *retval_ptr; + zend_arg_info *ret_info = EX(func)->common.arg_info - 1; + retval_ref = retval_ptr = EX_VAR(opline->op1.var); + + if (IS_CV == IS_CONST) { + ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr); + retval_ref = retval_ptr = EX_VAR(opline->result.var); + } else if (IS_CV == IS_VAR) { + if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) { + retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr); + } + ZVAL_DEREF(retval_ptr); + } else if (IS_CV == IS_CV) { + ZVAL_DEREF(retval_ptr); + } + + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) { + SAVE_OPLINE(); + retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) { + ZEND_VM_NEXT_OPCODE(); + } + } + + zend_reference *ref = NULL; + if (UNEXPECTED(retval_ref != retval_ptr)) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + ref = Z_REF_P(retval_ref); + } else { + /* A cast might happen - unwrap the reference if this is a by-value return */ + if (Z_REFCOUNT_P(retval_ref) == 1) { + ZVAL_UNREF(retval_ref); + } else { + Z_DELREF_P(retval_ref); + ZVAL_COPY(retval_ref, retval_ptr); + } + retval_ptr = retval_ref; + } + } + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, 1, 0))) { + zend_verify_return_error(EX(func), retval_ptr); + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +#endif + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_REF_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + SAVE_OPLINE(); + if (IS_UNUSED == IS_CONST) { + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + uint32_t arg_num; + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + } + + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + + ZEND_VM_NEXT_OPCODE(); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num; + + if (IS_UNUSED == IS_CONST) { + SAVE_OPLINE(); + zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num)); + if (UNEXPECTED(!arg)) { + + + HANDLE_EXCEPTION(); + } + } else { + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + arg_num = opline->op2.num; + } + + if (EXPECTED(1)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + varptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(varptr)) { + Z_ADDREF_P(varptr); + } else { + ZVAL_MAKE_REF_EX(varptr, 2); + } + ZVAL_REF(arg, Z_REF_P(varptr)); + + + ZEND_VM_NEXT_OPCODE(); + } + + varptr = EX_VAR(opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + if (IS_CV == IS_CV) { + ZVAL_COPY_DEREF(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (IS_CV == IS_TMP_VAR) { + /* pass */ + } else if (IS_CV == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CV == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_UNUSED != IS_UNUSED) { + zval *offset = NULL; + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_UNUSED != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CV != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_CV_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var = EX_VAR(opline->op1.var); + + if (Z_REFCOUNTED_P(var)) { + zend_refcounted *garbage = Z_COUNTED_P(var); + + ZVAL_UNDEF(var); + SAVE_OPLINE(); + GC_DTOR(garbage); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } else { + ZVAL_UNDEF(var); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + + varname = EX_VAR(opline->op1.var); + + if (IS_CV == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + varname = ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + + + HANDLE_EXCEPTION(); + } + } + + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + zend_hash_del_ind(target_symbol_table, name); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_SET_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = EX_VAR(opline->op1.var); + if (!(0)) { + if (Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { + ZEND_VM_SMART_BRANCH_TRUE(); + } else { + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else { + bool result; + + SAVE_OPLINE(); + result = !i_zend_is_true(value); + ZEND_VM_SMART_BRANCH(result, 1); + } +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_EMPTY_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + + value = EX_VAR(opline->op1.var); + if (!(1)) { + if (Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) { + ZEND_VM_SMART_BRANCH_TRUE(); + } else { + ZEND_VM_SMART_BRANCH_FALSE(); + } + } else { + bool result; + + SAVE_OPLINE(); + result = !i_zend_is_true(value); + ZEND_VM_SMART_BRANCH(result, 1); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + bool result; + zval *varname; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; + + SAVE_OPLINE(); + varname = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + if (IS_CV == IS_CONST) { + name = Z_STR_P(varname); + } else { + name = zval_get_tmp_string(varname, &tmp_name); + } + + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + value = zend_hash_find_ex(target_symbol_table, name, IS_CV == IS_CONST); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + + if (!value) { + result = (opline->extended_value & ZEND_ISEMPTY); + } else { + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + if (Z_ISREF_P(value)) { + value = Z_REFVAL_P(value); + } + result = Z_TYPE_P(value) > IS_NULL; + } else { + result = !i_zend_is_true(value); + } + } + + ZEND_VM_SMART_BRANCH(result, true); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INSTANCEOF_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr; + bool result; + + SAVE_OPLINE(); + expr = EX_VAR(opline->op1.var); + +try_instanceof: + if (Z_TYPE_P(expr) == IS_OBJECT) { + zend_class_entry *ce; + + if (IS_UNUSED == IS_CONST) { + ce = CACHED_PTR(opline->extended_value); + if (UNEXPECTED(ce == NULL)) { + ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD); + if (EXPECTED(ce)) { + CACHE_PTR(opline->extended_value, ce); + } + } + } else if (IS_UNUSED == IS_UNUSED) { + ce = zend_fetch_class(NULL, opline->op2.num); + if (UNEXPECTED(ce == NULL)) { + + + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } else { + ce = Z_CE_P(EX_VAR(opline->op2.var)); + } + result = ce && instanceof_function(Z_OBJCE_P(expr), ce); + } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) { + expr = Z_REFVAL_P(expr); + goto try_instanceof; + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + result = 0; + } + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CV == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + zval *key = NULL; + if ((IS_UNUSED & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CHECK_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1 = EX_VAR(opline->op1.var); + + if (UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) { + SAVE_OPLINE(); + ZVAL_UNDEFINED_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_MAKE_REF_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1 = EX_VAR(opline->op1.var); + + if (IS_CV == IS_CV) { + if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_NEW_EMPTY_REF(op1); + Z_SET_REFCOUNT_P(op1, 2); + ZVAL_NULL(Z_REFVAL_P(op1)); + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } else { + if (Z_ISREF_P(op1)) { + Z_ADDREF_P(op1); + } else { + ZVAL_MAKE_REF_EX(op1, 2); + } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) { + op1 = Z_INDIRECT_P(op1); + if (EXPECTED(!Z_ISREF_P(op1))) { + ZVAL_MAKE_REF_EX(op1, 2); + } else { + GC_ADDREF(Z_REF_P(op1)); + } + ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); + } else { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COUNT_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_long count; + + SAVE_OPLINE(); + op1 = EX_VAR(opline->op1.var); + + while (1) { + if (Z_TYPE_P(op1) == IS_ARRAY) { + count = zend_hash_num_elements(Z_ARRVAL_P(op1)); + break; + } else if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_object *zobj = Z_OBJ_P(op1); + + /* first, we check if the handler is defined */ + if (zobj->handlers->count_elements) { + if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) { + break; + } + if (UNEXPECTED(EG(exception))) { + count = 0; + break; + } + } + + /* if not and the object implements Countable we call its count() method */ + if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) { + zval retval; + + zend_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); + zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval); + count = zval_get_long(&retval); + zval_ptr_dtor(&retval); + break; + } + + /* If There's no handler and it doesn't implement Countable then emit a TypeError */ + } else if ((IS_CV & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + count = 0; + zend_type_error("%s(): Argument #1 ($value) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_value_name(op1)); + break; + } + + ZVAL_LONG(EX_VAR(opline->result.var), count); + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_COUNT_ARRAY_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_array *ht = Z_ARRVAL_P(EX_VAR(opline->op1.var)); + ZVAL_LONG(EX_VAR(opline->result.var), zend_hash_num_elements(ht)); + if (IS_CV & (IS_TMP_VAR|IS_VAR) && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + SAVE_OPLINE(); + zend_array_destroy(ht); + if (EG(exception)) { + HANDLE_EXCEPTION(); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_CLASS_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (IS_CV == IS_UNUSED) { + SAVE_OPLINE(); + if (UNEXPECTED(!EX(func)->common.scope)) { + zend_throw_error(NULL, "get_class() without arguments must be called from within a class"); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } else { + zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated"); + ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + ZEND_VM_NEXT_OPCODE(); + } + } else { + zval *op1; + + SAVE_OPLINE(); + op1 = EX_VAR(opline->op1.var); + while (1) { + if (Z_TYPE_P(op1) == IS_OBJECT) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name); + } else if ((IS_CV & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) { + op1 = Z_REFVAL_P(op1); + continue; + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(op1)); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + break; + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_GET_TYPE_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1; + zend_string *type; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + type = zend_zval_get_legacy_type(op1); + if (EXPECTED(type)) { + ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type); + } else { + ZVAL_STRING(EX_VAR(opline->result.var), "unknown type"); + } + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + uint32_t arg_num = opline->op2.num; + + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = EX_VAR(opline->op1.var); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_CV == IS_CV) { + ZVAL_COPY(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + ZVAL_COPY_VALUE(arg, varptr); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DIV_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + div_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POW_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + pow_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_CONCAT_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + + if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { + zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); + } + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } else { + SAVE_OPLINE(); + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + op1 = ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + op2 = ZVAL_UNDEFINED_OP2(); + } + concat_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_identical_function(op1, op2); + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_deref_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = fast_is_not_identical_function(op1, op2); + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CV == IS_CONST && IS_CV == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CV == IS_CONST && IS_CV == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CV == IS_CONST && IS_CV == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { +is_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_equal_double: + if (d1 == d2) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (result) { + goto is_equal_true; + } else { + goto is_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CV == IS_CONST && IS_CV == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_NONE(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_NONE(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CV == IS_CONST && IS_CV == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + double d1, d2; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if (1 && IS_CV == IS_CONST && IS_CV == IS_CONST) { + /* pass */ + } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { +is_not_equal_true: + ZEND_VM_SMART_BRANCH_TRUE_JMPNZ(); + } else { +is_not_equal_false: + ZEND_VM_SMART_BRANCH_FALSE_JMPNZ(); + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = (double)Z_LVAL_P(op1); + d2 = Z_DVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { + d1 = Z_DVAL_P(op1); + d2 = Z_DVAL_P(op2); +is_not_equal_double: + if (d1 != d2) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { + d1 = Z_DVAL_P(op1); + d2 = (double)Z_LVAL_P(op2); + goto is_not_equal_double; + } + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op1); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_str(op2); + } + if (!result) { + goto is_not_equal_true; + } else { + goto is_not_equal_false; + } + } + } + ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX op1, op2)); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_SPACESHIP_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + compare_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_BOOL_XOR_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + + SAVE_OPLINE(); + op1 = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + op2 = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + boolean_xor_function(EX_VAR(opline->result.var), op1, op2); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *value; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_op_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +assign_op_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + zend_reference *ref; + + do { + if (UNEXPECTED(Z_ISREF_P(zptr))) { + ref = Z_REF_P(zptr); + zptr = Z_REFVAL_P(zptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + if (prop_info) { + /* special case for typed properties */ + zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_binary_op(zptr, zptr, value OPLINE_CC); + } + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), zptr); + } + } + } else { + zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value, *container, *dim; + HashTable *ht; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +assign_dim_op_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +assign_dim_op_new_array: + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_UNUSED) { + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); + if (UNEXPECTED(!var_ptr)) { + zend_cannot_add_element(); + goto assign_dim_op_ret_null; + } + } else { + if (IS_CV == IS_CONST) { + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); + } else { + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(!var_ptr)) { + goto assign_dim_op_ret_null; + } + } + + value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + } else { + if (EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto assign_dim_op_array; + } + } + + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); + } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + uint8_t old_type; + + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } + } + goto assign_dim_op_new_array; + } else { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); +assign_dim_op_ret_null: + FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OP_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *var_ptr; + zval *value; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + var_ptr = _get_zval_ptr_cv_BP_VAR_RW(opline->op1.var EXECUTE_DATA_CC); + + do { + if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { + zend_reference *ref = Z_REF_P(var_ptr); + var_ptr = Z_REFVAL_P(var_ptr); + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { + zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); + break; + } + } + zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); + } while (0); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_PRE_INC_OBJ_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto pre_incdec_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +pre_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + UNDEF_RESULT(); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); + zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_POST_INC_OBJ_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object; + zval *property; + zval *zptr; + void *_cache_slot[3] = {0}; + void **cache_slot; + zend_property_info *prop_info; + zend_object *zobj; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto post_incdec_object; + } + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); + break; + } + +post_incdec_object: + /* here we are sure we are dealing with an object */ + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + name = Z_STR_P(property); + } else { + name = zval_try_get_tmp_string(property, &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + cache_slot = (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot; + if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { + if (UNEXPECTED(Z_ISERROR_P(zptr))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); + zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); + } + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_R_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *dim, *value; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + dim = EX_VAR(opline->op2.var); + if (IS_CV != IS_CONST) { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { +fetch_dim_r_array: + value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto fetch_dim_r_array; + } else { + goto fetch_dim_r_slow; + } + } else { +fetch_dim_r_slow: + if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); + } + } else { + zend_fetch_dimension_address_read_R(container, dim, IS_CV OPLINE_CC EXECUTE_DATA_CC); + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_W_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_W(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_RW_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_RW(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_IS_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_read_IS(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_W_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + if (IS_CV == IS_UNUSED) { + ZEND_VM_TAIL_CALL(zend_use_undef_in_read_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_DIM_R_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + zend_fetch_dimension_address_UNSET(container, EX_VAR(opline->op2.var), IS_CV OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_R_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + zend_wrong_property_read(container, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_r_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_r_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { +fetch_obj_r_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + prop_offset = prop_info->offset; + goto fetch_obj_r_simple; + } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) { + zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET]; + ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION); + ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array)); + + uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (IS_CV & IS_CV) { + GC_ADDREF(zobj); + } + if (IS_CV & (IS_CV|IS_VAR|IS_TMP_VAR)) { + call_info |= ZEND_CALL_RELEASE_THIS; + } + zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj); + call->prev_execute_data = execute_data; + call->call = NULL; + call->return_value = EX_VAR(opline->result.var); + call->run_time_cache = RUN_TIME_CACHE(&hook->op_array); + + execute_data = call; + EG(current_execute_data) = execute_data; + zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC); + +#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)) + opline = hook->op_array.opcodes; +#else + EX(opline) = hook->op_array.opcodes; +#endif + LOAD_OPLINE_EX(); + + + + + ZEND_VM_ENTER_EX(); + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_r_copy; + } else { + goto fetch_obj_r_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + +#if ZEND_DEBUG + /* For non-standard object handlers, verify a declared property type in debug builds. + * Fetch prop_info before calling read_property(), as it may deallocate the object. */ + zend_property_info *prop_info = NULL; + if (zobj->handlers->read_property != zend_std_read_property) { + prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); + } +#endif + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); +#if ZEND_DEBUG + if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO + && ZEND_TYPE_IS_SET(prop_info->type)) { + ZVAL_OPT_DEREF(retval); + zend_verify_property_type(prop_info, retval, /* strict */ true); + } +#endif + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_r_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_r_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_W_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address( + result, container, IS_CV, property, IS_CV, + ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), + BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_RW_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *result; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_IS_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + void **cache_slot = NULL; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + 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)) { + break; + } + } + if (IS_CV == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + } + ZVAL_NULL(EX_VAR(opline->result.var)); + goto fetch_obj_is_finish; + } while (0); + } + + /* here we are sure we are dealing with an object */ + do { + zend_object *zobj = Z_OBJ_P(container); + zend_string *name, *tmp_name; + zval *retval; + + if (IS_CV == IS_CONST) { + cache_slot = CACHE_ADDR(opline->extended_value); + + if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { +fetch_obj_is_simple: + retval = OBJ_PROP(zobj, prop_offset); + if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { +fetch_obj_is_fast_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + ZEND_VM_NEXT_OPCODE(); + } + } + } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) { + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) { + zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + goto fetch_obj_is_simple; + } + /* Fall through to read_property for hooks. */ + } else if (EXPECTED(zobj->properties != NULL)) { + ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset)); + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { + uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); + + if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { + 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)))) { + retval = &p->val; + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); + } + retval = zend_hash_find_known_hash(zobj->properties, name); + if (EXPECTED(retval)) { + uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + if (0 || (IS_CV & (IS_TMP_VAR|IS_VAR)) != 0) { + goto fetch_obj_is_copy; + } else { + goto fetch_obj_is_fast_copy; + } + } + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + break; + } + } + + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + if (retval != EX_VAR(opline->result.var)) { +fetch_obj_is_copy: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); + } + } while (0); + +fetch_obj_is_finish: + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ +#if 0 + USE_OPLINE +#endif + + if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { + /* Behave like FETCH_OBJ_W */ + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { + ZEND_VM_TAIL_CALL(zend_use_tmp_in_write_context_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_W_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZEND_VM_TAIL_CALL(ZEND_FETCH_OBJ_R_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container, *property, *result; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + result = EX_VAR(opline->result.var); + zend_fetch_property_address(result, container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC); + + + if (IS_CV == IS_VAR) { + FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CONST == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_VAR == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object, *value, tmp; + zend_object *zobj; + zend_string *name, *tmp_name; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + object = EX_VAR(opline->op1.var); + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { + object = Z_REFVAL_P(object); + goto assign_object; + } + zend_throw_non_object_error(object, _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC) OPLINE_CC EXECUTE_DATA_CC); + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + +assign_object: + zobj = Z_OBJ_P(object); + if (IS_CV == IS_CONST) { + if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { + void **cache_slot = CACHE_ADDR(opline->extended_value); + uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); + zval *property_val; + zend_property_info *prop_info; + + if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { + prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); + +assign_obj_simple: + property_val = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property_val) != IS_UNDEF) { + if (prop_info != NULL) { + value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC); + goto free_and_exit_assign_obj; + } else { +fast_assign_obj: + value = zend_assign_to_variable_ex(property_val, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) { + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + if (UNEXPECTED(zend_lazy_object_must_init(zobj))) { + zobj = zend_lazy_object_init(zobj); + if (!zobj) { + value = &EG(uninitialized_zval); + goto free_and_exit_assign_obj; + } + } + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + rebuild_object_properties_internal(zobj); + } + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(zobj->properties); + } + zobj->properties = zend_array_dup(zobj->properties); + } + property_val = zend_hash_find_known_hash(zobj->properties, name); + if (property_val) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (GC_DELREF(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else { + value = Z_REFVAL_P(value); + Z_TRY_ADDREF_P(value); + } + } else if (IS_CV == IS_CV) { + Z_TRY_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, name, value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset)); + if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) { + prop_info = CACHED_PTR_EX(cache_slot + 2); + prop_offset = prop_info->offset; + if (!ZEND_TYPE_IS_SET(prop_info->type)) { + prop_info = NULL; + } + goto assign_obj_simple; + } + /* Fall through to write_property for hooks. */ + } + } + name = Z_STR_P(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC)); + } else { + name = zval_try_get_tmp_string(_get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC), &tmp_name); + if (UNEXPECTED(!name)) { + + + UNDEF_RESULT(); + goto exit_assign_obj; + } + } + + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + + value = zobj->handlers->write_property(zobj, name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +free_and_exit_assign_obj: + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); + } + + +exit_assign_obj: + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + + + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CONST == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CONST == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = RT_CONSTANT((opline+1), (opline+1)->op1); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_TMP_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_TMP_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_VAR == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_VAR == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *object_ptr, *orig_object_ptr; + zval *value; + zval *variable_ptr; + zval *dim; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + orig_object_ptr = object_ptr = EX_VAR(opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + SEPARATE_ARRAY(object_ptr); + if (IS_CV == IS_UNUSED) { + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + HashTable *ht = Z_ARRVAL_P(object_ptr); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + if (IS_CV == IS_CV || IS_CV == IS_VAR) { + ZVAL_DEREF(value); + } + value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); + if (UNEXPECTED(value == NULL)) { + zend_cannot_add_element(); + goto assign_dim_error; + } else if (IS_CV == IS_CV) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } else if (IS_CV == IS_VAR) { + zval *free_op_data = EX_VAR((opline+1)->op1.var); + if (Z_ISREF_P(free_op_data)) { + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + zval_ptr_dtor_nogc(free_op_data); + } + } else if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(value))) { + Z_ADDREF_P(value); + } + } + } else { + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CONST) { + variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } else { + variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); + } + if (UNEXPECTED(variable_ptr == NULL)) { + goto assign_dim_error; + } + value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + dim++; + } + + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (IS_CV == IS_UNUSED) { + zend_use_new_element_for_string(); + + + UNDEF_RESULT(); + } else { + dim = EX_VAR(opline->op2.var); + value = EX_VAR((opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + if (Z_ISREF_P(orig_object_ptr) + && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) + && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + + UNDEF_RESULT(); + } else { + HashTable *ht = zend_new_array(8); + uint8_t old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } + goto try_assign_dim_array; + } + } else { + zend_use_scalar_as_array(); + dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); +assign_dim_error: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (IS_CV != IS_UNUSED) { + + + } + + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(0)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (0 || UNEXPECTED(1)) { + zend_refcounted *garbage = NULL; + + value = zend_assign_to_variable_ex(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES(), &garbage); + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (garbage) { + GC_DTOR_NO_REF(garbage); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } + + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_REF_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *variable_ptr; + zval *value_ptr; + zend_refcounted *garbage = NULL; + + SAVE_OPLINE(); + value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC); + variable_ptr = EX_VAR(opline->op1.var); + + if (IS_CV == IS_VAR && + UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { + + zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); + variable_ptr = &EG(uninitialized_zval); + } else if (IS_CV == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!Z_ISREF_P(value_ptr))) { + + variable_ptr = zend_wrong_assign_to_variable_reference( + variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + + if (garbage) { + GC_DTOR(garbage); + } + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_VAR_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_CV == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_CV, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *property, *container, *value_ptr; + + SAVE_OPLINE(); + + container = EX_VAR(opline->op1.var); + property = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + value_ptr = _get_zval_ptr_cv_BP_VAR_W((opline+1)->op1.var EXECUTE_DATA_CC); + + if (1) { + if (IS_CV == IS_UNUSED) { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } else { + if (IS_CV == IS_CONST) { + zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } else { + zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + } + } else { + zend_assign_to_property_reference(container, IS_CV, property, IS_CV, value_ptr OPLINE_CC EXECUTE_DATA_CC); + } + + + + + + + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_FAST_CONCAT_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + zend_string *op1_str, *op2_str, *str; + + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && + (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { + zend_string *op1_str = Z_STR_P(op1); + zend_string *op2_str = Z_STR_P(op2); + zend_string *str; + uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); + + if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + } else if (IS_CV != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST || IS_CV == IS_CV) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); + } else { + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } 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); + + 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); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } else { + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + GC_ADD_FLAGS(str, flags); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV & (IS_TMP_VAR|IS_VAR)) { + zend_string_release_ex(op2_str, 0); + } + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CV == IS_CONST) { + op1_str = Z_STR_P(op1); + } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { + op1_str = zend_string_copy(Z_STR_P(op1)); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + op1_str = zval_get_string_func(op1); + } + if (IS_CV == IS_CONST) { + op2_str = Z_STR_P(op2); + } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { + op2_str = zend_string_copy(Z_STR_P(op2)); + } else { + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + } + op2_str = zval_get_string_func(op2); + } + do { + if (IS_CV != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op2))) { + GC_ADDREF(op2_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op2_str); + zend_string_release_ex(op1_str, 0); + break; + } + } + if (IS_CV != IS_CONST) { + if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_REFCOUNTED_P(op1))) { + GC_ADDREF(op1_str); + } + } + ZVAL_STR(EX_VAR(opline->result.var), op1_str); + zend_string_release_ex(op2_str, 0); + break; + } + } + str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); + memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); + memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); + + ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str); + ZVAL_NEW_STR(EX_VAR(opline->result.var), str); + if (IS_CV != IS_CONST) { + zend_string_release_ex(op1_str, 0); + } + if (IS_CV != IS_CONST) { + zend_string_release_ex(op2_str, 0); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_METHOD_CALL_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *function_name; + zval *object; + zend_function *fbc; + zend_class_entry *called_scope; + zend_object *obj; + zend_execute_data *call; + uint32_t call_info; + + SAVE_OPLINE(); + + object = EX_VAR(opline->op1.var); + + if (IS_CV != IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + if (IS_CV != IS_CONST && + UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { + do { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP2(); + if (UNEXPECTED(EG(exception) != NULL)) { + + + HANDLE_EXCEPTION(); + } + } + zend_throw_error(NULL, "Method name must be a string"); + + + + + HANDLE_EXCEPTION(); + } while (0); + } + + if (IS_CV == IS_UNUSED) { + obj = Z_OBJ_P(object); + } else { + do { + if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + } else { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) { + zend_reference *ref = Z_REF_P(object); + + object = &ref->val; + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + obj = Z_OBJ_P(object); + if (IS_CV & IS_VAR) { + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else { + Z_ADDREF_P(object); + } + } + break; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { + object = ZVAL_UNDEFINED_OP1(); + if (UNEXPECTED(EG(exception) != NULL)) { + if (IS_CV != IS_CONST) { + + + } + HANDLE_EXCEPTION(); + } + } + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + zend_invalid_method_call(object, function_name); + + + + + HANDLE_EXCEPTION(); + } + } while (0); + } + + called_scope = obj->ce; + + if (IS_CV == IS_CONST && + EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) { + fbc = CACHED_PTR(opline->result.num + sizeof(void*)); + } else { + zend_object *orig_obj = obj; + + if (IS_CV == IS_CONST) { + function_name = EX_VAR(opline->op2.var); + } + + /* First, locate the function. */ + fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL)); + if (UNEXPECTED(fbc == NULL)) { + if (EXPECTED(!EG(exception))) { + zend_undefined_method(orig_obj->ce, Z_STR_P(function_name)); + } + + + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + HANDLE_EXCEPTION(); + } + if (IS_CV == IS_CONST && + EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) && + EXPECTED(obj == orig_obj)) { + CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc); + } + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) { + GC_ADDREF(obj); /* For $this pointer */ + if (GC_DELREF(orig_obj) == 0) { + zend_objects_store_del(orig_obj); + } + } + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) { + init_func_run_time_cache(&fbc->op_array); + } + } + + if (IS_CV != IS_CONST) { + + + } + + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) { + if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + /* call static method */ + obj = (zend_object*)called_scope; + call_info = ZEND_CALL_NESTED_FUNCTION; + } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) { + if (IS_CV == IS_CV) { + GC_ADDREF(obj); /* For $this pointer */ + } + /* CV may be changed indirectly (e.g. when it's a reference) */ + call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS; + } + + call = zend_vm_stack_push_call_frame(call_info, + fbc, opline->extended_value, obj); + call->prev_execute_data = EX(call); + EX(call) = call; + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *expr_ptr, new_expr; + + SAVE_OPLINE(); + if ((IS_CV == IS_VAR || IS_CV == IS_CV) && + UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + expr_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + if (Z_ISREF_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } else { + ZVAL_MAKE_REF_EX(expr_ptr, 2); + } + + + } else { + expr_ptr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + if (IS_CV == IS_TMP_VAR) { + /* pass */ + } else if (IS_CV == IS_CONST) { + Z_TRY_ADDREF_P(expr_ptr); + } else if (IS_CV == IS_CV) { + ZVAL_DEREF(expr_ptr); + Z_TRY_ADDREF_P(expr_ptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(expr_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(expr_ptr); + + expr_ptr = Z_REFVAL_P(expr_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + ZVAL_COPY_VALUE(&new_expr, expr_ptr); + expr_ptr = &new_expr; + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) { + Z_ADDREF_P(expr_ptr); + } + } + } + } + + if (IS_CV != IS_UNUSED) { + zval *offset = EX_VAR(opline->op2.var); + zend_string *str; + zend_ulong hval; + +add_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index; + } + } +str_index: + zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index: + zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto add_again; + } else if (Z_TYPE_P(offset) == IS_NULL) { + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + str = ZSTR_EMPTY_ALLOC(); + goto str_index; + } else { + zend_illegal_array_offset_access(offset); + zval_ptr_dtor_nogc(expr_ptr); + } + + + } else { + if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) { + zend_cannot_add_element(); + zval_ptr_dtor_nogc(expr_ptr); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_INIT_ARRAY_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array; + uint32_t size; + USE_OPLINE + + SAVE_OPLINE(); + array = EX_VAR(opline->result.var); + if (IS_CV != IS_UNUSED) { + size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT; + ZVAL_ARR(array, zend_new_array(size)); + /* Explicitly initialize array as not-packed if flag is set */ + if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) { + zend_hash_real_init_mixed(Z_ARRVAL_P(array)); + } + ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } else { + ZVAL_ARR(array, zend_new_array(0)); + ZEND_VM_NEXT_OPCODE(); + } +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_DIM_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_ulong hval; + zend_string *key; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = EX_VAR(opline->op2.var); + + do { + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + +unset_dim_array: + SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); +offset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + key = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(key, hval)) { + goto num_index_dim; + } + } +str_index_dim: + ZEND_ASSERT(ht != &EG(symbol_table)); + zend_hash_del(ht, key); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_dim: + zend_hash_index_del(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) { + offset = Z_REFVAL_P(offset); + goto offset_again; + } else if (Z_TYPE_P(offset) == IS_DOUBLE) { + hval = zend_dval_to_lval_safe(Z_DVAL_P(offset)); + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_NULL) { + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else if (Z_TYPE_P(offset) == IS_FALSE) { + hval = 0; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_TRUE) { + hval = 1; + goto num_index_dim; + } else if (Z_TYPE_P(offset) == IS_RESOURCE) { + zend_use_resource_as_offset(offset); + hval = Z_RES_HANDLE_P(offset); + goto num_index_dim; + } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) { + ZVAL_UNDEFINED_OP2(); + key = ZSTR_EMPTY_ALLOC(); + goto str_index_dim; + } else { + zend_illegal_array_offset_unset(offset); + } + break; + } else if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto unset_dim_array; + } + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + container = ZVAL_UNDEFINED_OP1(); + } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) { + offset = ZVAL_UNDEFINED_OP2(); + } + if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { + zend_throw_error(NULL, "Cannot unset string offsets"); + } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) { + zend_throw_error(NULL, "Cannot unset offset in a non-array variable"); + } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_UNSET_OBJ_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + do { + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + if (Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (Z_TYPE_P(container) != IS_OBJECT) { + if (IS_CV == IS_CV + && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + break; + } + } else { + break; + } + } + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + break; + } + } + Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL)); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + } while (0); + + + + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + bool result; + zend_ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = EX_VAR(opline->op1.var); + offset = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + HashTable *ht; + zval *value; + zend_string *str; + +isset_dim_obj_array: + ht = Z_ARRVAL_P(container); +isset_again: + if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + if (ZEND_HANDLE_NUMERIC(str, hval)) { + goto num_index_prop; + } + } + value = zend_hash_find_ex(ht, str, IS_CV == IS_CONST); + } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { + offset = Z_REFVAL_P(offset); + goto isset_again; + } else { + value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); + if (UNEXPECTED(EG(exception))) { + result = 0; + goto isset_dim_obj_exit; + } + } + + if (!(opline->extended_value & ZEND_ISEMPTY)) { + /* > IS_NULL means not IS_UNDEF and not IS_NULL */ + result = value != NULL && Z_TYPE_P(value) > IS_NULL && + (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); + + if (IS_CV & (IS_CONST|IS_CV)) { + /* avoid exception check */ + + + ZEND_VM_SMART_BRANCH(result, 0); + } + } else { + result = (value == NULL || !i_zend_is_true(value)); + } + goto isset_dim_obj_exit; + } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { + container = Z_REFVAL_P(container); + if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { + goto isset_dim_obj_array; + } + } + + if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { + offset++; + } + if (!(opline->extended_value & ZEND_ISEMPTY)) { + result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); + } else { + result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); + } + +isset_dim_obj_exit: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + int result; + zval *offset; + zend_string *name, *tmp_name; + + SAVE_OPLINE(); + container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + + if (IS_CV == IS_CONST || + (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { + container = Z_REFVAL_P(container); + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } else { + result = (opline->extended_value & ZEND_ISEMPTY); + goto isset_object_finish; + } + } + + if (IS_CV == IS_CONST) { + name = Z_STR_P(offset); + } else { + name = zval_try_get_tmp_string(offset, &tmp_name); + if (UNEXPECTED(!name)) { + result = 0; + goto isset_object_finish; + } + } + + result = + (opline->extended_value & ZEND_ISEMPTY) ^ + Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + +isset_object_finish: + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *key, *subject; + HashTable *ht; + bool result; + + SAVE_OPLINE(); + + key = EX_VAR(opline->op1.var); + subject = EX_VAR(opline->op2.var); + + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { +array_key_exists_array: + ht = Z_ARRVAL_P(subject); + result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + } else { + if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { + subject = Z_REFVAL_P(subject); + if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { + goto array_key_exists_array; + } + } + zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); + result = 0; + } + + + + + ZEND_VM_SMART_BRANCH(result, 1); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_YIELD_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + + SAVE_OPLINE(); + if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { + ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + /* Destroy the previously yielded value */ + zval_ptr_dtor(&generator->value); + + /* Destroy the previously yielded key */ + zval_ptr_dtor(&generator->key); + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { + zval *value; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } + } else { + zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + do { + if (IS_CV == IS_VAR) { + ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); + if (opline->extended_value == ZEND_RETURNS_FUNCTION + && !Z_ISREF_P(value_ptr)) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + ZVAL_COPY(&generator->value, value_ptr); + break; + } + } + if (Z_ISREF_P(value_ptr)) { + Z_ADDREF_P(value_ptr); + } else { + ZVAL_MAKE_REF_EX(value_ptr, 2); + } + ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); + } while (0); + + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST) { + ZVAL_COPY_VALUE(&generator->value, value); + if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { + Z_ADDREF(generator->value); + } + } 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)) { + ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); + + + } else { + ZVAL_COPY_VALUE(&generator->value, value); + if (IS_CV == IS_CV) { + if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + } + } + } + } else { + /* If no value was specified yield null */ + ZVAL_NULL(&generator->value); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { + key = Z_REFVAL_P(key); + } + ZVAL_COPY(&generator->key, key); + + + if (Z_TYPE(generator->key) == IS_LONG + && Z_LVAL(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL(generator->key); + } + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + ZVAL_LONG(&generator->key, generator->largest_used_integer_key); + } + + if (RETURN_VALUE_USED(opline)) { + /* If the return value of yield is used set the send + * target and initialize it to NULL */ + generator->send_target = EX_VAR(opline->result.var); + ZVAL_NULL(generator->send_target); + } else { + generator->send_target = NULL; + } + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */ + /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */ + /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *op1, *op2; + bool result; + + op1 = EX_VAR(opline->op1.var); + op2 = EX_VAR(opline->op2.var); + result = fast_is_identical_function(op1, op2); + /* Free is a no-op for const/cv */ + ZEND_VM_SMART_BRANCH(!result, 0); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ +} + +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HALT_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return (zend_op*) ZEND_VM_ENTER_BIT; +} + +/* The following helpers can not tailcall due to signature mismatch. Redefine some macros so they do not enforce tailcall. */ +#pragma push_macro("ZEND_VM_CONTINUE") +#undef ZEND_VM_CONTINUE +#pragma push_macro("ZEND_VM_INTERRUPT") +#undef ZEND_VM_INTERRUPT +#define ZEND_VM_CONTINUE(handler) return opline +#define ZEND_VM_INTERRUPT() return zend_interrupt_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_add_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + add_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_sub_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + sub_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_mul_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + mul_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_mod_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + mod_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_shift_left_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + shift_left_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_shift_right_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + shift_right_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + int ret; + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + ret = zend_compare(op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_SMART_BRANCH(ret == 0, 1); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_not_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + int ret; + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + ret = zend_compare(op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_SMART_BRANCH(ret != 0, 1); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_smaller_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + int ret; + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + ret = zend_compare(op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_SMART_BRANCH(ret < 0, 1); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_is_smaller_or_equal_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + int ret; + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + ret = zend_compare(op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_SMART_BRANCH(ret <= 0, 1); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_or_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + bitwise_or_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_and_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + bitwise_and_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_xor_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + bitwise_xor_function(EX_VAR(opline->result.var), op_1, op_2); + if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_1); + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_bw_not_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + bitwise_not_function(EX_VAR(opline->result.var), op_1); + FREE_OP(opline->op1_type, opline->op1.var); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type) +{ + USE_OPLINE + zval *prop; + zend_property_info *prop_info; + + SAVE_OPLINE(); + + prop = zend_fetch_static_property_address( + &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, + type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); + if (UNEXPECTED(!prop)) { + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + prop = &EG(uninitialized_zval); + } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) + && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) + && UNEXPECTED(!zend_asymmetric_property_has_set_access(prop_info))) { + if (Z_TYPE_P(prop) == IS_OBJECT) { + goto copy_deref; + } else if (type != BP_VAR_UNSET || Z_TYPE_P(prop) != IS_UNDEF) { + zend_asymmetric_visibility_property_modification_error(prop_info, "indirectly modify"); + } + prop = &EG(uninitialized_zval); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { +copy_deref: + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), prop); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), prop); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ +static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_cannot_pass_by_ref_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t _arg_num, zval *_arg) +{ + USE_OPLINE + + SAVE_OPLINE(); + + zend_cannot_pass_by_reference(_arg_num); + FREE_OP(opline->op1_type, opline->op1.var); + ZVAL_UNDEF(_arg); + HANDLE_EXCEPTION(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_verify_recv_arg_type_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1) +{ + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1))) { + HANDLE_EXCEPTION(); + } + + ZEND_VM_NEXT_OPCODE(); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_case_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX zval *op_1, zval *op_2) +{ + int ret; + USE_OPLINE + + SAVE_OPLINE(); + if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { + op_1 = ZVAL_UNDEFINED_OP1(); + } + if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { + op_2 = ZVAL_UNDEFINED_OP2(); + } + ret = zend_compare(op_1, op_2); + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + zval_ptr_dtor_nogc(op_2); + } + ZEND_VM_SMART_BRANCH(ret == 0, 1); +} + +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_dispatch_try_catch_finally_helper_SPEC_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t try_catch_offset, uint32_t op_num) +{ + /* May be NULL during generator closing (only finally blocks are executed) */ + zend_object *ex = EG(exception); + + /* Walk try/catch/finally structures upwards, performing the necessary actions */ + for (; try_catch_offset != (uint32_t) -1; try_catch_offset--) { + zend_try_catch_element *try_catch = + &EX(func)->op_array.try_catch_array[try_catch_offset]; + + if (op_num < try_catch->catch_op && ex) { + /* Go to catch block */ + cleanup_live_vars(execute_data, op_num, try_catch->catch_op); + ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0); + + } else if (op_num < try_catch->finally_op) { + if (ex && zend_is_unwind_exit(ex)) { + /* Don't execute finally blocks on exit (for now) */ + continue; + } + + /* Go to finally block */ + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var); + cleanup_live_vars(execute_data, op_num, try_catch->finally_op); + Z_OBJ_P(fast_call) = EG(exception); + EG(exception) = NULL; + Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1; + ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0); + + } else if (op_num < try_catch->finally_end) { + zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var); + + /* cleanup incomplete RETURN statement */ + if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1 + && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) { + zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var); + + zval_ptr_dtor(return_value); + } + + /* Chain potential exception from wrapping finally block */ + if (Z_OBJ_P(fast_call)) { + if (ex) { + if (zend_is_unwind_exit(ex) || zend_is_graceful_exit(ex)) { + /* discard the previously thrown exception */ + OBJ_RELEASE(Z_OBJ_P(fast_call)); + } else { + zend_exception_set_previous(ex, Z_OBJ_P(fast_call)); + } + } else { + ex = EG(exception) = Z_OBJ_P(fast_call); + } + } + } + } + + /* Uncaught exception */ + + /* Don't use 0 because it gets replaced by zend_vm_gen.php. */ + if (zend_observer_fcall_op_array_extension != -1) { + zend_observer_fcall_end(execute_data, NULL); + } + cleanup_live_vars(execute_data, op_num, 0); + if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) { + zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); + EG(current_execute_data) = EX(prev_execute_data); + zend_generator_close(generator, 1); + ZEND_VM_RETURN(); + } else { + /* We didn't execute RETURN, and have to initialize return_value */ + if (EX(return_value)) { + ZVAL_UNDEF(EX(return_value)); + } + ZEND_VM_DISPATCH_TO_LEAVE_HELPER(zend_leave_helper_SPEC_TAILCALL); + } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_fetch_var_address_helper_SPEC_CONST_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE - zval *container; - bool result; - zend_ulong hval; - zval *offset; + zval *varname; + zval *retval; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; SAVE_OPLINE(); - container = EX_VAR(opline->op1.var); - offset = EX_VAR(opline->op2.var); - - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - HashTable *ht; - zval *value; - zend_string *str; + varname = RT_CONSTANT(opline, opline->op1); -isset_dim_obj_array: - ht = Z_ARRVAL_P(container); -isset_again: - if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) { - str = Z_STR_P(offset); - if (IS_CV != IS_CONST) { - if (ZEND_HANDLE_NUMERIC(str, hval)) { - goto num_index_prop; - } - } - value = zend_hash_find_ex(ht, str, IS_CV == IS_CONST); - } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) { - hval = Z_LVAL_P(offset); -num_index_prop: - value = zend_hash_index_find(ht, hval); - } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) { - offset = Z_REFVAL_P(offset); - goto isset_again; - } else { - value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC); - if (UNEXPECTED(EG(exception))) { - result = 0; - goto isset_dim_obj_exit; - } + if (IS_CONST == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; + } else { + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - if (!(opline->extended_value & ZEND_ISEMPTY)) { - /* > IS_NULL means not IS_UNDEF and not IS_NULL */ - result = value != NULL && Z_TYPE_P(value) > IS_NULL && - (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL); - if (IS_CV & (IS_CONST|IS_CV)) { - /* avoid exception check */ + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } - ZEND_VM_SMART_BRANCH(result, 0); + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + retval = zend_hash_find_ex(target_symbol_table, name, IS_CONST == IS_CONST); + if (retval == NULL) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { +fetch_this: + zend_fetch_this_var(type OPLINE_CC EXECUTE_DATA_CC); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + if (type == BP_VAR_W) { + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); } else { - result = (value == NULL || !i_zend_is_true(value)); + if (IS_CONST == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); + } else { + retval = &EG(uninitialized_zval); + } + if (IS_CONST == IS_CV) { + zend_string_release(name); + } } - goto isset_dim_obj_exit; - } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) { - container = Z_REFVAL_P(container); - if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { - goto isset_dim_obj_array; + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { + goto fetch_this; + } + if (type == BP_VAR_W) { + ZVAL_NULL(retval); + } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + } else { + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + ZVAL_NULL(retval); + } else { + retval = &EG(uninitialized_zval); + } + } } } - if (IS_CV == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) { - offset++; - } - if (!(opline->extended_value & ZEND_ISEMPTY)) { - result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC); - } else { - result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC); - } + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { -isset_dim_obj_exit: + } - ZEND_VM_SMART_BRANCH(result, 1); + if (IS_CONST != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE - zval *container; - int result; - zval *offset; + zval *varname; + zval *retval; zend_string *name, *tmp_name; + HashTable *target_symbol_table; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + varname = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - if (IS_CV == IS_CONST || - (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { - if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { - container = Z_REFVAL_P(container); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); + } + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } - } else { - result = (opline->extended_value & ZEND_ISEMPTY); - goto isset_object_finish; + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); } } - if (IS_CV == IS_CONST) { - name = Z_STR_P(offset); - } else { - name = zval_try_get_tmp_string(offset, &tmp_name); - if (UNEXPECTED(!name)) { - result = 0; - goto isset_object_finish; + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + retval = zend_hash_find_ex(target_symbol_table, name, (IS_TMP_VAR|IS_VAR) == IS_CONST); + if (retval == NULL) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { +fetch_this: + zend_fetch_this_var(type OPLINE_CC EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_tmp_string_release(tmp_name); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + if (type == BP_VAR_W) { + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + } else { + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); + } else { + retval = &EG(uninitialized_zval); + } + if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + zend_string_release(name); + } + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { + goto fetch_this; + } + if (type == BP_VAR_W) { + ZVAL_NULL(retval); + } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + } else { + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + ZVAL_NULL(retval); + } else { + retval = &EG(uninitialized_zval); + } + } } } - result = - (opline->extended_value & ZEND_ISEMPTY) ^ - Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((IS_CV == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL)); + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + } - if (IS_CV != IS_CONST) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { zend_tmp_string_release(tmp_name); } -isset_object_finish: - - - ZEND_VM_SMART_BRANCH(result, 1); + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV_EX zend_fetch_var_address_helper_SPEC_CV_UNUSED_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_EX int type) { USE_OPLINE - - zval *key, *subject; - HashTable *ht; - bool result; + zval *varname; + zval *retval; + zend_string *name, *tmp_name; + HashTable *target_symbol_table; SAVE_OPLINE(); + varname = EX_VAR(opline->op1.var); - key = EX_VAR(opline->op1.var); - subject = EX_VAR(opline->op2.var); - - if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { -array_key_exists_array: - ht = Z_ARRVAL_P(subject); - result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV == IS_CONST) { + name = Z_STR_P(varname); + } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { + name = Z_STR_P(varname); + tmp_name = NULL; } else { - if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) { - subject = Z_REFVAL_P(subject); - if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { - goto array_key_exists_array; - } + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { + ZVAL_UNDEFINED_OP1(); } - zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC); - result = 0; - } - - - ZEND_VM_SMART_BRANCH(result, 1); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + name = zval_try_get_tmp_string(varname, &tmp_name); + if (UNEXPECTED(!name)) { + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C); - SAVE_OPLINE(); - if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) { - ZEND_VM_TAIL_CALL(zend_yield_in_closed_generator_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } } - /* Destroy the previously yielded value */ - zval_ptr_dtor(&generator->value); - - /* Destroy the previously yielded key */ - zval_ptr_dtor(&generator->key); - - /* Set the new yielded value */ - if (IS_CV != IS_UNUSED) { - if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - /* Constants and temporary variables aren't yieldable by reference, - * but we still allow them with a notice. */ - if (IS_CV & (IS_CONST|IS_TMP_VAR)) { - zval *value; - - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - - value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } - } else { - zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(opline->op1.var EXECUTE_DATA_CC); - - /* If a function call result is yielded and the function did - * not return by reference we throw a notice. */ - do { - if (IS_CV == IS_VAR) { - ZEND_ASSERT(value_ptr != &EG(uninitialized_zval)); - if (opline->extended_value == ZEND_RETURNS_FUNCTION - && !Z_ISREF_P(value_ptr)) { - zend_error(E_NOTICE, "Only variable references should be yielded by reference"); - ZVAL_COPY(&generator->value, value_ptr); - break; - } - } - if (Z_ISREF_P(value_ptr)) { - Z_ADDREF_P(value_ptr); - } else { - ZVAL_MAKE_REF_EX(value_ptr, 2); - } - ZVAL_REF(&generator->value, Z_REF_P(value_ptr)); - } while (0); - + target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); + retval = zend_hash_find_ex(target_symbol_table, name, IS_CV == IS_CONST); + if (retval == NULL) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { +fetch_this: + zend_fetch_this_var(type OPLINE_CC EXECUTE_DATA_CC); + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + if (type == BP_VAR_W) { + retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); + } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); } else { - zval *value = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC); - - /* Consts, temporary variables and references need copying */ - if (IS_CV == IS_CONST) { - ZVAL_COPY_VALUE(&generator->value, value); - if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) { - Z_ADDREF(generator->value); - } - } 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)) { - ZVAL_COPY(&generator->value, Z_REFVAL_P(value)); - + if (IS_CV == IS_CV) { + /* Keep name alive in case an error handler tries to free it. */ + zend_string_addref(name); + } + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); } else { - ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV == IS_CV) { - if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value); + retval = &EG(uninitialized_zval); + } + if (IS_CV == IS_CV) { + zend_string_release(name); + } + } + /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ + } else if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { + goto fetch_this; + } + if (type == BP_VAR_W) { + ZVAL_NULL(retval); + } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + } else { + zend_error_unchecked(E_WARNING, "Undefined %svariable $%S", + (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name); + if (type == BP_VAR_RW && !EG(exception)) { + ZVAL_NULL(retval); + } else { + retval = &EG(uninitialized_zval); } } } - } else { - /* If no value was specified yield null */ - ZVAL_NULL(&generator->value); } - /* Set the new yielded key */ - if (IS_CV != IS_UNUSED) { - zval *key = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - if ((IS_CV & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) { - key = Z_REFVAL_P(key); - } - ZVAL_COPY(&generator->key, key); + if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { - if (Z_TYPE(generator->key) == IS_LONG - && Z_LVAL(generator->key) > generator->largest_used_integer_key - ) { - generator->largest_used_integer_key = Z_LVAL(generator->key); - } - } else { - /* If no key was specified we use auto-increment keys */ - generator->largest_used_integer_key++; - ZVAL_LONG(&generator->key, generator->largest_used_integer_key); - } - if (RETURN_VALUE_USED(opline)) { - /* If the return value of yield is used set the send - * target and initialize it to NULL */ - generator->send_target = EX_VAR(opline->result.var); - ZVAL_NULL(generator->send_target); - } else { - generator->send_target = NULL; } - /* The GOTO VM uses a local opline variable. We need to set the opline - * variable in execute_data so we don't resume at an old position. */ - SAVE_OPLINE(); - - ZEND_VM_RETURN(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */ - /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */ - /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */ - USE_OPLINE - zval *op1, *op2; - bool result; - - op1 = EX_VAR(opline->op1.var); - op2 = EX_VAR(opline->op2.var); - result = fast_is_identical_function(op1, op2); - /* Free is a no-op for const/cv */ - ZEND_VM_SMART_BRANCH(result, 0); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *op1, *op2; - bool result; - - op1 = EX_VAR(opline->op1.var); - op2 = EX_VAR(opline->op2.var); - result = fast_is_identical_function(op1, op2); - /* Free is a no-op for const/cv */ - ZEND_VM_SMART_BRANCH(!result, 0); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE + if (IS_CV != IS_CONST) { + zend_tmp_string_release(tmp_name); + } - SAVE_OPLINE(); - zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ + ZEND_ASSERT(retval != NULL); + if (type == BP_VAR_R || type == BP_VAR_IS) { + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } - -#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) -# undef ZEND_VM_TAIL_CALL -# undef ZEND_VM_CONTINUE -# undef ZEND_VM_RETURN - -# define ZEND_VM_TAIL_CALL(call) call; ZEND_VM_CONTINUE() -# define ZEND_VM_CONTINUE() HYBRID_NEXT() -# define ZEND_VM_RETURN() goto HYBRID_HALT_LABEL -#endif - +#pragma pop_macro("ZEND_VM_INTERRUPT") +#pragma pop_macro("ZEND_VM_CONTINUE") +#endif /* ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL */ #if (ZEND_VM_KIND != ZEND_VM_KIND_CALL) && (ZEND_GCC_VERSION >= 4000) && !defined(__clang__) # pragma GCC push_options # pragma GCC optimize("no-gcse") # pragma GCC optimize("no-ivopts") #endif -#ifdef _WIN64 +#if defined(_WIN64) && defined(_M_X64) /* See save_xmm_x86_64_ms_masm.asm */ void execute_ex_real(zend_execute_data *ex) #else @@ -55170,7 +112064,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) if (UNEXPECTED(execute_data == NULL)) { - static const void * const labels[] = { + static zend_vm_opcode_handler_t const labels[] = { (void*)&&ZEND_NOP_SPEC_LABEL, (void*)&&ZEND_ADD_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_ADD_SPEC_CONST_TMPVARCV_LABEL, @@ -58666,8 +115560,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_LABEL, (void*)&&ZEND_NULL_LABEL }; - zend_opcode_handlers = (const void **) labels; - zend_handlers_count = sizeof(labels) / sizeof(void*); + zend_opcode_handlers = (zend_vm_opcode_handler_t*) labels; + zend_handlers_count = sizeof(labels) / sizeof(labels[0]); memset(&hybrid_halt_op, 0, sizeof(hybrid_halt_op)); hybrid_halt_op.handler = (void*)&&HYBRID_HALT_LABEL; #ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE @@ -58698,10 +115592,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) HYBRID_SWITCH() { #else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */ #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) - ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + (OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (UNEXPECTED(!OPLINE)) { #else - opline = ((opcode_handler_t)opline->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + opline = (opline->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) { #endif #endif /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */ @@ -58780,7 +115674,10 @@ ZEND_API void execute_ex(zend_execute_data *ex) { zend_execute_data *old_execute_data; uint32_t call_info = EX_CALL_INFO(); +#if ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL + /* zend_leave_helper may be called with opline=call_leave_op in TAILCALL VM */ SAVE_OPLINE(); +#endif if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { EG(current_execute_data) = EX(prev_execute_data); @@ -59227,9 +116124,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) zval *retval_ptr; zval *return_value; + retval_ptr = RT_CONSTANT(opline, opline->op1); return_value = EX(return_value); + if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -59295,6 +116194,9 @@ ZEND_API void execute_ex(zend_execute_data *ex) + + + goto zend_leave_helper_SPEC_LABEL; } @@ -61256,9 +118158,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) zval *retval_ptr; zval *return_value; + retval_ptr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC); return_value = EX(return_value); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -61305,7 +118209,376 @@ ZEND_API void execute_ex(zend_execute_data *ex) } ZVAL_COPY_VALUE(return_value, retval_ptr); } while (0); - } else /* if (IS_TMP_VAR == IS_VAR) */ { + } else /* if (IS_TMP_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + + retval_ptr = Z_REFVAL_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (UNEXPECTED(GC_DELREF(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } else { + ZVAL_COPY_VALUE(return_value, retval_ptr); + } + } + } + + + + + + + goto zend_leave_helper_SPEC_LABEL; +} + + VM_TRACE_OP_END(ZEND_RETURN_SPEC_TMP) + HYBRID_CASE(ZEND_RETURN_BY_REF_SPEC_TMP): + VM_TRACE(ZEND_RETURN_BY_REF_SPEC_TMP) + ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_RETURN_BY_REF_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_GENERATOR_RETURN_SPEC_TMP): + VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_TMP) + ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_GENERATOR_RETURN_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_USER_SPEC_TMP): + VM_TRACE(ZEND_SEND_USER_SPEC_TMP) + ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_SEND_USER_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CAST_SPEC_TMP): + VM_TRACE(ZEND_CAST_SPEC_TMP) + ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_CAST_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FE_RESET_R_SPEC_TMP): + VM_TRACE(ZEND_FE_RESET_R_SPEC_TMP) + ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FE_RESET_R_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FE_RESET_RW_SPEC_TMP): + VM_TRACE(ZEND_FE_RESET_RW_SPEC_TMP) + ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FE_RESET_RW_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_END_SILENCE_SPEC_TMP): + VM_TRACE(ZEND_END_SILENCE_SPEC_TMP) + ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_END_SILENCE_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_JMP_SET_SPEC_TMP): + VM_TRACE(ZEND_JMP_SET_SPEC_TMP) + ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_JMP_SET_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_COALESCE_SPEC_TMP): + VM_TRACE(ZEND_COALESCE_SPEC_TMP) + ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_COALESCE_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_JMP_NULL_SPEC_TMP): + VM_TRACE(ZEND_JMP_NULL_SPEC_TMP) + ZEND_JMP_NULL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_JMP_NULL_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_QM_ASSIGN_SPEC_TMP): + VM_TRACE(ZEND_QM_ASSIGN_SPEC_TMP) + ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_QM_ASSIGN_SPEC_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST): + VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST) + ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_IS_IDENTICAL_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CONST): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CONST) + ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST): + VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST) + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST): + VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST) + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_CONST): + VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_CONST) + ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ROPE_ADD_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ROPE_END_SPEC_TMP_CONST): + VM_TRACE(ZEND_ROPE_END_SPEC_TMP_CONST) + ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ROPE_END_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_CONST): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_CONST) + ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_SEND_VAL_EX_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST): + VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST) + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_CONST): + VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_CONST) + ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_TMP_CONST): + VM_TRACE(ZEND_YIELD_SPEC_TMP_CONST) + ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_IN_ARRAY_SPEC_TMP_CONST): + VM_TRACE(ZEND_IN_ARRAY_SPEC_TMP_CONST) + ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_IN_ARRAY_SPEC_TMP_CONST) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR) + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR) + ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ROPE_END_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_ROPE_END_SPEC_TMP_TMPVAR) + ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ROPE_END_SPEC_TMP_TMPVAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR) + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR) + ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_TMP_TMPVAR): + VM_TRACE(ZEND_YIELD_SPEC_TMP_TMPVAR) + ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_TMPVAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP): + VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP) + ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_IS_IDENTICAL_SPEC_TMP_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_TMP): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_TMP) + ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP): + VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP) + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_VAR): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_VAR) + ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_VAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED) + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED) + ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED) + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK): + VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK) + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED) + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_UNUSED) + ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_YIELD_SPEC_TMP_UNUSED) + ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_GET_TYPE_SPEC_TMP_UNUSED): + VM_TRACE(ZEND_GET_TYPE_SPEC_TMP_UNUSED) + ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_GET_TYPE_SPEC_TMP_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CV): + VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CV) + ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV): + VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV) + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV): + VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_CV): + VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_CV) + ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ROPE_ADD_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ROPE_END_SPEC_TMP_CV): + VM_TRACE(ZEND_ROPE_END_SPEC_TMP_CV) + ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ROPE_END_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV): + VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV) + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_CV): + VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_CV) + ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_YIELD_SPEC_TMP_CV): + VM_TRACE(ZEND_YIELD_SPEC_TMP_CV) + ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_BIND_LEXICAL_SPEC_TMP_CV): + VM_TRACE(ZEND_BIND_LEXICAL_SPEC_TMP_CV) + ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_BIND_LEXICAL_SPEC_TMP_CV) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED): + VM_TRACE(ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED) + ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_PRE_INC_SPEC_VAR_RETVAL_USED): + VM_TRACE(ZEND_PRE_INC_SPEC_VAR_RETVAL_USED) + ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_PRE_INC_SPEC_VAR_RETVAL_USED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED): + VM_TRACE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED) + ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED): + VM_TRACE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED) + ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_POST_INC_SPEC_VAR): + VM_TRACE(ZEND_POST_INC_SPEC_VAR) + ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_POST_INC_SPEC_VAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_POST_DEC_SPEC_VAR): + VM_TRACE(ZEND_POST_DEC_SPEC_VAR) + ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + VM_TRACE_OP_END(ZEND_POST_DEC_SPEC_VAR) + HYBRID_BREAK(); + HYBRID_CASE(ZEND_RETURN_SPEC_VAR): + VM_TRACE(ZEND_RETURN_SPEC_VAR) +{ + USE_OPLINE + zval *retval_ptr; + zval *return_value; + + + retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); + return_value = EX(return_value); + + + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { + SAVE_OPLINE(); + retval_ptr = ZVAL_UNDEFINED_OP1(); + if (return_value) { + ZVAL_NULL(return_value); + } + } else if (!return_value) { + if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { + if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { + SAVE_OPLINE(); + rc_dtor_func(Z_COUNTED_P(retval_ptr)); + } + } + } else { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { + Z_ADDREF_P(return_value); + } + } + } else if (IS_VAR == IS_CV) { + do { + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { + if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { + zend_refcounted *ref = Z_COUNTED_P(retval_ptr); + ZVAL_COPY_VALUE(return_value, retval_ptr); + if (GC_MAY_LEAK(ref)) { + SAVE_OPLINE(); + gc_possible_root(ref); + } + ZVAL_NULL(retval_ptr); + break; + } else { + Z_ADDREF_P(retval_ptr); + } + } else { + retval_ptr = Z_REFVAL_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) { + Z_ADDREF_P(retval_ptr); + } + } + } + ZVAL_COPY_VALUE(return_value, retval_ptr); + } while (0); + } else /* if (IS_VAR == IS_VAR) */ { if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { zend_refcounted *ref = Z_COUNTED_P(retval_ptr); @@ -61324,367 +118597,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) - goto zend_leave_helper_SPEC_LABEL; -} - - VM_TRACE_OP_END(ZEND_RETURN_SPEC_TMP) - HYBRID_CASE(ZEND_RETURN_BY_REF_SPEC_TMP): - VM_TRACE(ZEND_RETURN_BY_REF_SPEC_TMP) - ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_RETURN_BY_REF_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_GENERATOR_RETURN_SPEC_TMP): - VM_TRACE(ZEND_GENERATOR_RETURN_SPEC_TMP) - ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_GENERATOR_RETURN_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_USER_SPEC_TMP): - VM_TRACE(ZEND_SEND_USER_SPEC_TMP) - ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_SEND_USER_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_CAST_SPEC_TMP): - VM_TRACE(ZEND_CAST_SPEC_TMP) - ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_CAST_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FE_RESET_R_SPEC_TMP): - VM_TRACE(ZEND_FE_RESET_R_SPEC_TMP) - ZEND_FE_RESET_R_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FE_RESET_R_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FE_RESET_RW_SPEC_TMP): - VM_TRACE(ZEND_FE_RESET_RW_SPEC_TMP) - ZEND_FE_RESET_RW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FE_RESET_RW_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_END_SILENCE_SPEC_TMP): - VM_TRACE(ZEND_END_SILENCE_SPEC_TMP) - ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_END_SILENCE_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_JMP_SET_SPEC_TMP): - VM_TRACE(ZEND_JMP_SET_SPEC_TMP) - ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_JMP_SET_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_COALESCE_SPEC_TMP): - VM_TRACE(ZEND_COALESCE_SPEC_TMP) - ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_COALESCE_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_JMP_NULL_SPEC_TMP): - VM_TRACE(ZEND_JMP_NULL_SPEC_TMP) - ZEND_JMP_NULL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_JMP_NULL_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_QM_ASSIGN_SPEC_TMP): - VM_TRACE(ZEND_QM_ASSIGN_SPEC_TMP) - ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_QM_ASSIGN_SPEC_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST): - VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_CONST) - ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_IS_IDENTICAL_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CONST): - VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CONST) - ZEND_CASE_STRICT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST): - VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST) - ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST): - VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST) - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST): - VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_CONST): - VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_CONST) - ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ROPE_ADD_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ROPE_END_SPEC_TMP_CONST): - VM_TRACE(ZEND_ROPE_END_SPEC_TMP_CONST) - ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ROPE_END_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_CONST): - VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_CONST) - ZEND_SEND_VAL_EX_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_SEND_VAL_EX_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST): - VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST) - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_CONST): - VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_CONST) - ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_CONST): - VM_TRACE(ZEND_YIELD_SPEC_TMP_CONST) - ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_IN_ARRAY_SPEC_TMP_CONST): - VM_TRACE(ZEND_IN_ARRAY_SPEC_TMP_CONST) - ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_IN_ARRAY_SPEC_TMP_CONST) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR): - VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR) - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR): - VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR): - VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR) - ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ROPE_ADD_SPEC_TMP_TMPVAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ROPE_END_SPEC_TMP_TMPVAR): - VM_TRACE(ZEND_ROPE_END_SPEC_TMP_TMPVAR) - ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ROPE_END_SPEC_TMP_TMPVAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR): - VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR) - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR): - VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR) - ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_TMPVAR): - VM_TRACE(ZEND_YIELD_SPEC_TMP_TMPVAR) - ZEND_YIELD_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_TMPVAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP): - VM_TRACE(ZEND_IS_IDENTICAL_SPEC_TMP_TMP) - ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_IS_IDENTICAL_SPEC_TMP_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_TMP): - VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_TMP) - ZEND_CASE_STRICT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP): - VM_TRACE(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP) - ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_VAR): - VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_VAR) - ZEND_CASE_STRICT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_VAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED): - VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED) - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED): - VM_TRACE(ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED) - ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED): - VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED) - ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK): - VM_TRACE(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK) - ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED): - VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED) - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_UNUSED): - VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_UNUSED) - ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_UNUSED): - VM_TRACE(ZEND_YIELD_SPEC_TMP_UNUSED) - ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_GET_TYPE_SPEC_TMP_UNUSED): - VM_TRACE(ZEND_GET_TYPE_SPEC_TMP_UNUSED) - ZEND_GET_TYPE_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_GET_TYPE_SPEC_TMP_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_CASE_STRICT_SPEC_TMP_CV): - VM_TRACE(ZEND_CASE_STRICT_SPEC_TMP_CV) - ZEND_CASE_STRICT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_CASE_STRICT_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV): - VM_TRACE(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV) - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV): - VM_TRACE(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ROPE_ADD_SPEC_TMP_CV): - VM_TRACE(ZEND_ROPE_ADD_SPEC_TMP_CV) - ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ROPE_ADD_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ROPE_END_SPEC_TMP_CV): - VM_TRACE(ZEND_ROPE_END_SPEC_TMP_CV) - ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ROPE_END_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV): - VM_TRACE(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV) - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_INIT_ARRAY_SPEC_TMP_CV): - VM_TRACE(ZEND_INIT_ARRAY_SPEC_TMP_CV) - ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_INIT_ARRAY_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_YIELD_SPEC_TMP_CV): - VM_TRACE(ZEND_YIELD_SPEC_TMP_CV) - ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_YIELD_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_BIND_LEXICAL_SPEC_TMP_CV): - VM_TRACE(ZEND_BIND_LEXICAL_SPEC_TMP_CV) - ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_BIND_LEXICAL_SPEC_TMP_CV) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED): - VM_TRACE(ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED) - ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_PRE_INC_SPEC_VAR_RETVAL_USED): - VM_TRACE(ZEND_PRE_INC_SPEC_VAR_RETVAL_USED) - ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_PRE_INC_SPEC_VAR_RETVAL_USED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED): - VM_TRACE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED) - ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED): - VM_TRACE(ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED) - ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_POST_INC_SPEC_VAR): - VM_TRACE(ZEND_POST_INC_SPEC_VAR) - ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_POST_INC_SPEC_VAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_POST_DEC_SPEC_VAR): - VM_TRACE(ZEND_POST_DEC_SPEC_VAR) - ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - VM_TRACE_OP_END(ZEND_POST_DEC_SPEC_VAR) - HYBRID_BREAK(); - HYBRID_CASE(ZEND_RETURN_SPEC_VAR): - VM_TRACE(ZEND_RETURN_SPEC_VAR) -{ - USE_OPLINE - zval *retval_ptr; - zval *return_value; - - retval_ptr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); - return_value = EX(return_value); - - if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { - SAVE_OPLINE(); - retval_ptr = ZVAL_UNDEFINED_OP1(); - if (return_value) { - ZVAL_NULL(return_value); - } - } else if (!return_value) { - if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { - if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) { - SAVE_OPLINE(); - rc_dtor_func(Z_COUNTED_P(retval_ptr)); - } - } - } else { - if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { - ZVAL_COPY_VALUE(return_value, retval_ptr); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) { - Z_ADDREF_P(return_value); - } - } - } else if (IS_VAR == IS_CV) { - do { - if (Z_OPT_REFCOUNTED_P(retval_ptr)) { - if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) { - if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) { - zend_refcounted *ref = Z_COUNTED_P(retval_ptr); - ZVAL_COPY_VALUE(return_value, retval_ptr); - if (GC_MAY_LEAK(ref)) { - SAVE_OPLINE(); - gc_possible_root(ref); - } - ZVAL_NULL(retval_ptr); - break; - } else { - Z_ADDREF_P(retval_ptr); - } - } else { - retval_ptr = Z_REFVAL_P(retval_ptr); - if (Z_OPT_REFCOUNTED_P(retval_ptr)) { - Z_ADDREF_P(retval_ptr); - } - } - } - ZVAL_COPY_VALUE(return_value, retval_ptr); - } while (0); - } else /* if (IS_VAR == IS_VAR) */ { - if (UNEXPECTED(Z_ISREF_P(retval_ptr))) { - zend_refcounted *ref = Z_COUNTED_P(retval_ptr); - - retval_ptr = Z_REFVAL_P(retval_ptr); - ZVAL_COPY_VALUE(return_value, retval_ptr); - if (UNEXPECTED(GC_DELREF(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { - Z_ADDREF_P(retval_ptr); - } - } else { - ZVAL_COPY_VALUE(return_value, retval_ptr); - } - } - } @@ -63034,9 +119946,11 @@ ZEND_API void execute_ex(zend_execute_data *ex) zval *retval_ptr; zval *return_value; + retval_ptr = EX_VAR(opline->op1.var); return_value = EX(return_value); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) { SAVE_OPLINE(); retval_ptr = ZVAL_UNDEFINED_OP1(); @@ -63102,6 +120016,9 @@ ZEND_API void execute_ex(zend_execute_data *ex) + + + goto zend_leave_helper_SPEC_LABEL; } @@ -64398,7 +121315,7 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) void zend_vm_init(void) { - static const void * const labels[] = { + static zend_vm_opcode_handler_func_t const funcs[] = { ZEND_NOP_SPEC_HANDLER, ZEND_ADD_SPEC_CONST_CONST_HANDLER, ZEND_ADD_SPEC_CONST_TMPVARCV_HANDLER, @@ -67894,6 +124811,3508 @@ void zend_vm_init(void) ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER, ZEND_NULL_HANDLER }; +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL || ZEND_VM_KIND == ZEND_VM_KIND_SWITCH + static zend_vm_opcode_handler_t const handlers[] = { + ZEND_NOP_SPEC_TAILCALL_HANDLER, + ZEND_ADD_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_ADD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_SUB_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_DIV_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_MOD_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_MOD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_MOD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MOD_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MOD_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_SL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SR_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_SR_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SR_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SR_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CONCAT_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_OR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_AND_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_POW_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_POW_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_POW_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POW_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POW_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POW_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_POW_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_POW_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POW_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_BW_NOT_SPEC_CONST_TAILCALL_HANDLER, + ZEND_BW_NOT_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_BW_NOT_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BW_NOT_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_BOOL_NOT_SPEC_CONST_TAILCALL_HANDLER, + ZEND_BOOL_NOT_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_BOOL_NOT_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BOOL_NOT_SPEC_CV_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_TMP_TMP_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_VAR_TMP_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_VAR_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_TMP_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_TMP_TAILCALL_HANDLER, + ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OP_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_OP_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_STATIC_PROP_OP_SPEC_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_REF_SPEC_VAR_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_REF_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_REF_SPEC_CV_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_REF_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_SPEC_CONST_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_SPEC_TMP_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_SPEC_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_VAR_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_UNUSED_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_CONST_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_TMPVAR_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ASSIGN_OBJ_REF_SPEC_CV_CV_OP_DATA_CV_TAILCALL_HANDLER, + ZEND_ASSIGN_STATIC_PROP_REF_SPEC_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_INC_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_INC_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_INC_SPEC_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_DEC_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_DEC_SPEC_CV_TAILCALL_HANDLER, + ZEND_PRE_INC_STATIC_PROP_SPEC_TAILCALL_HANDLER, + ZEND_POST_INC_STATIC_PROP_SPEC_TAILCALL_HANDLER, + ZEND_JMP_SPEC_TAILCALL_HANDLER, + ZEND_JMPZ_SPEC_CONST_TAILCALL_HANDLER, + ZEND_JMPZ_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_JMPZ_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_JMPZ_SPEC_CV_TAILCALL_HANDLER, + ZEND_JMPNZ_SPEC_CONST_TAILCALL_HANDLER, + ZEND_JMPNZ_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_JMPNZ_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_JMPNZ_SPEC_CV_TAILCALL_HANDLER, + ZEND_JMPZ_EX_SPEC_CONST_TAILCALL_HANDLER, + ZEND_JMPZ_EX_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_JMPZ_EX_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_JMPZ_EX_SPEC_CV_TAILCALL_HANDLER, + ZEND_JMPNZ_EX_SPEC_CONST_TAILCALL_HANDLER, + ZEND_JMPNZ_EX_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_JMPNZ_EX_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_JMPNZ_EX_SPEC_CV_TAILCALL_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_CHECK_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_VAR_NO_REF_EX_SPEC_VAR_UNUSED_QUICK_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CAST_SPEC_CONST_TAILCALL_HANDLER, + ZEND_CAST_SPEC_TMP_TAILCALL_HANDLER, + ZEND_CAST_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CAST_SPEC_CV_TAILCALL_HANDLER, + ZEND_BOOL_SPEC_CONST_TAILCALL_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BOOL_SPEC_CV_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_ROPE_END_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_ROPE_END_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_ROPE_END_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ROPE_END_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_BEGIN_SILENCE_SPEC_TAILCALL_HANDLER, + ZEND_END_SILENCE_SPEC_TMP_TAILCALL_HANDLER, + ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_TAILCALL_HANDLER, + ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_DO_FCALL_SPEC_RETVAL_USED_TAILCALL_HANDLER, + ZEND_DO_FCALL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_DO_FCALL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_INIT_FCALL_SPEC_CONST_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_CONST_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_TMP_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_VAR_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_CV_TAILCALL_HANDLER, + ZEND_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_RECV_SPEC_UNUSED_TAILCALL_HANDLER, + ZEND_RECV_INIT_SPEC_CONST_TAILCALL_HANDLER, + ZEND_SEND_VAL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_UNUSED_QUICK_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_UNUSED_QUICK_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_REF_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_REF_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_REF_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_REF_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NEW_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NEW_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NEW_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_TAILCALL_HANDLER, + ZEND_FREE_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_CONST_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_CV_TAILCALL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_UNSET_VAR_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FE_RESET_R_SPEC_CONST_TAILCALL_HANDLER, + ZEND_FE_RESET_R_SPEC_TMP_TAILCALL_HANDLER, + ZEND_FE_RESET_R_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FE_RESET_R_SPEC_CV_TAILCALL_HANDLER, + ZEND_FE_FETCH_R_SPEC_VAR_TAILCALL_HANDLER, + ZEND_FETCH_R_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_R_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_W_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_W_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_RW_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_RW_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_IS_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_IS_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_UNSET_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_LIST_R_SPEC_TMPVARCV_CV_TAILCALL_HANDLER, + ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_CHECK_FUNC_ARG_SPEC_UNUSED_UNUSED_QUICK_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_EXT_STMT_SPEC_TAILCALL_HANDLER, + ZEND_EXT_FCALL_BEGIN_SPEC_TAILCALL_HANDLER, + ZEND_EXT_FCALL_END_SPEC_TAILCALL_HANDLER, + ZEND_EXT_NOP_SPEC_TAILCALL_HANDLER, + ZEND_TICKS_SPEC_TAILCALL_HANDLER, + ZEND_SEND_VAR_NO_REF_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_NO_REF_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CATCH_SPEC_CONST_TAILCALL_HANDLER, + ZEND_THROW_SPEC_CONST_TAILCALL_HANDLER, + ZEND_THROW_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_THROW_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_THROW_SPEC_CV_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_CLONE_SPEC_CONST_TAILCALL_HANDLER, + ZEND_CLONE_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_CLONE_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_CLONE_SPEC_UNUSED_TAILCALL_HANDLER, + ZEND_CLONE_SPEC_CV_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_CONST_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_TMP_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_VAR_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_CV_TAILCALL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_UNUSED_QUICK_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_UNUSED_QUICK_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_SEND_ARRAY_SPEC_TAILCALL_HANDLER, + ZEND_SEND_USER_SPEC_CONST_TAILCALL_HANDLER, + ZEND_SEND_USER_SPEC_TMP_TAILCALL_HANDLER, + ZEND_SEND_USER_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_USER_SPEC_CV_TAILCALL_HANDLER, + ZEND_STRLEN_SPEC_CONST_TAILCALL_HANDLER, + ZEND_STRLEN_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_STRLEN_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_STRLEN_SPEC_CV_TAILCALL_HANDLER, + ZEND_DEFINED_SPEC_CONST_TAILCALL_HANDLER, + ZEND_TYPE_CHECK_SPEC_CONST_TAILCALL_HANDLER, + ZEND_TYPE_CHECK_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_TYPE_CHECK_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_TYPE_CHECK_SPEC_CV_TAILCALL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_TAILCALL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_FE_RESET_RW_SPEC_CONST_TAILCALL_HANDLER, + ZEND_FE_RESET_RW_SPEC_TMP_TAILCALL_HANDLER, + ZEND_FE_RESET_RW_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FE_RESET_RW_SPEC_CV_TAILCALL_HANDLER, + ZEND_FE_FETCH_RW_SPEC_VAR_TAILCALL_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_TAILCALL_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_CV_TAILCALL_HANDLER, + ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_DO_ICALL_SPEC_RETVAL_USED_TAILCALL_HANDLER, + ZEND_DO_ICALL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_DO_ICALL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_DO_UCALL_SPEC_RETVAL_USED_TAILCALL_HANDLER, + ZEND_DO_UCALL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_DO_UCALL_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_TAILCALL_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_ECHO_SPEC_CONST_TAILCALL_HANDLER, + ZEND_ECHO_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_ECHO_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ECHO_SPEC_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_VAR_TAILCALL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_GENERATOR_CREATE_SPEC_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MAKE_REF_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MAKE_REF_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_DECLARE_FUNCTION_SPEC_TAILCALL_HANDLER, + ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_TAILCALL_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_DECLARE_CLASS_SPEC_CONST_TAILCALL_HANDLER, + ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_DECLARE_ANON_CLASS_SPEC_TAILCALL_HANDLER, + ZEND_ADD_ARRAY_UNPACK_SPEC_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_HANDLE_EXCEPTION_SPEC_TAILCALL_HANDLER, + ZEND_USER_OPCODE_SPEC_TAILCALL_HANDLER, + ZEND_ASSERT_CHECK_SPEC_TAILCALL_HANDLER, + ZEND_JMP_SET_SPEC_CONST_TAILCALL_HANDLER, + ZEND_JMP_SET_SPEC_TMP_TAILCALL_HANDLER, + ZEND_JMP_SET_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_JMP_SET_SPEC_CV_TAILCALL_HANDLER, + ZEND_UNSET_CV_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_SET_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_CV_SPEC_CV_UNUSED_EMPTY_TAILCALL_HANDLER, + ZEND_FETCH_LIST_W_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_LIST_W_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_LIST_W_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_SEPARATE_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_CV_TAILCALL_HANDLER, + ZEND_CALL_TRAMPOLINE_SPEC_TAILCALL_HANDLER, + ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_TMP_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_TMP_UNUSED_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_VAR_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CV_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_YIELD_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_CONST_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_TMP_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_VAR_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_CV_TAILCALL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_FAST_CALL_SPEC_TAILCALL_HANDLER, + ZEND_FAST_RET_SPEC_TAILCALL_HANDLER, + ZEND_RECV_VARIADIC_SPEC_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_UNPACK_SPEC_TAILCALL_HANDLER, + ZEND_YIELD_FROM_SPEC_CONST_TAILCALL_HANDLER, + ZEND_YIELD_FROM_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_YIELD_FROM_SPEC_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_YIELD_FROM_SPEC_CV_TAILCALL_HANDLER, + ZEND_COPY_TMP_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_BIND_GLOBAL_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_COALESCE_SPEC_CONST_TAILCALL_HANDLER, + ZEND_COALESCE_SPEC_TMP_TAILCALL_HANDLER, + ZEND_COALESCE_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_COALESCE_SPEC_CV_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SPACESHIP_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_FUNC_NUM_ARGS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_FUNC_GET_ARGS_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FUNC_GET_ARGS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_TAILCALL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_TAILCALL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_TAILCALL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_TAILCALL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TAILCALL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TAILCALL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_BIND_LEXICAL_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_BIND_STATIC_SPEC_CV_TAILCALL_HANDLER, + ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_FUNC_ARG_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_FUNC_ARG_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_SWITCH_LONG_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SWITCH_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SWITCH_STRING_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SWITCH_STRING_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IN_ARRAY_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_IN_ARRAY_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_IN_ARRAY_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IN_ARRAY_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_COUNT_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_COUNT_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_COUNT_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_COUNT_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_GET_CLASS_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_GET_CLASS_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_GET_CLASS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_GET_CLASS_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_GET_CALLED_CLASS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_GET_TYPE_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_GET_TYPE_SPEC_TMP_UNUSED_TAILCALL_HANDLER, + ZEND_GET_TYPE_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_GET_TYPE_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CV_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_TMPVAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CV_TMPVAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ARRAY_KEY_EXISTS_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_MATCH_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_MATCH_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MATCH_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MATCH_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_CONST_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_TMP_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_TMP_CV_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_CONST_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_TMP_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_CASE_STRICT_SPEC_VAR_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MATCH_ERROR_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_TAILCALL_HANDLER, + ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MATCH_ERROR_SPEC_TMPVARCV_UNUSED_TAILCALL_HANDLER, + ZEND_JMP_NULL_SPEC_CONST_TAILCALL_HANDLER, + ZEND_JMP_NULL_SPEC_TMP_TAILCALL_HANDLER, + ZEND_JMP_NULL_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_JMP_NULL_SPEC_CV_TAILCALL_HANDLER, + ZEND_CHECK_UNDEF_ARGS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_FETCH_GLOBALS_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_VERIFY_NEVER_TYPE_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_CALLABLE_CONVERT_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_BIND_INIT_STATIC_OR_JMP_SPEC_CV_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_0_SPEC_UNUSED_UNUSED_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_0_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_1_SPEC_UNUSED_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_1_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_2_SPEC_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_2_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_3_SPEC_TAILCALL_HANDLER, + ZEND_FRAMELESS_ICALL_3_SPEC_OBSERVER_TAILCALL_HANDLER, + ZEND_JMP_FRAMELESS_SPEC_CONST_TAILCALL_HANDLER, + ZEND_INIT_PARENT_PROPERTY_HOOK_CALL_SPEC_CONST_UNUSED_TAILCALL_HANDLER, + ZEND_DECLARE_ATTRIBUTED_CONST_SPEC_CONST_CONST_TAILCALL_HANDLER, + ZEND_INIT_FCALL_OFFSET_SPEC_CONST_TAILCALL_HANDLER, + ZEND_RECV_NOTYPE_SPEC_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_COUNT_ARRAY_SPEC_TMPVAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_COUNT_ARRAY_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_JMP_FORWARD_SPEC_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_ADD_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SUB_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_NO_OVERFLOW_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_MUL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_IDENTICAL_NOTHROW_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_NOT_IDENTICAL_NOTHROW_SPEC_CV_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_LONG_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_CONST_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_CONST_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPZ_TAILCALL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_TAILCALL_HANDLER, + ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_INC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_INC_LONG_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_DEC_LONG_NO_OVERFLOW_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_PRE_DEC_LONG_SPEC_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_POST_INC_LONG_NO_OVERFLOW_SPEC_CV_TAILCALL_HANDLER, + ZEND_POST_INC_LONG_SPEC_CV_TAILCALL_HANDLER, + ZEND_POST_DEC_LONG_NO_OVERFLOW_SPEC_CV_TAILCALL_HANDLER, + ZEND_POST_DEC_LONG_SPEC_CV_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_LONG_SPEC_CONST_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_LONG_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_DOUBLE_SPEC_CONST_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_DOUBLE_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_NOREF_SPEC_CONST_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_QM_ASSIGN_NOREF_SPEC_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_CONST_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_TMPVAR_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_CV_CONST_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_FETCH_DIM_R_INDEX_SPEC_CV_TMPVARCV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_SIMPLE_SPEC_VAR_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_SIMPLE_SPEC_CV_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_UNUSED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER, + ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_UNUSED_TAILCALL_HANDLER, + ZEND_SEND_VAL_SIMPLE_SPEC_CONST_TAILCALL_HANDLER, + ZEND_SEND_VAL_EX_SIMPLE_SPEC_CONST_TAILCALL_HANDLER, + ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_TAILCALL_HANDLER, + ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_TAILCALL_HANDLER, + ZEND_NULL_TAILCALL_HANDLER + }; + zend_handlers_count = sizeof(handlers) / sizeof(handlers[0]); +#elif ZEND_VM_KIND != ZEND_VM_KIND_HYBRID + static zend_vm_opcode_handler_t const *handlers = funcs; + zend_handlers_count = sizeof(funcs) / sizeof(funcs[0]); +#endif static const uint32_t specs[] = { 0, 1 | SPEC_RULE_OP1 | SPEC_RULE_OP2, @@ -68152,13 +128571,17 @@ void zend_vm_init(void) 3493, 3493, }; -#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) - zend_opcode_handler_funcs = labels; +#if 0 +#elif (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) + zend_opcode_handler_funcs = funcs; zend_spec_handlers = specs; execute_ex(NULL); +#elif ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + zend_opcode_handler_funcs = funcs; + zend_opcode_handlers = handlers; + zend_spec_handlers = specs; #else - zend_opcode_handlers = labels; - zend_handlers_count = sizeof(labels) / sizeof(void*); + zend_opcode_handlers = handlers; zend_spec_handlers = specs; #endif VM_TRACE_START(); @@ -68200,7 +128623,7 @@ ZEND_API void ZEND_FASTCALL zend_serialize_opcode_handler(zend_op *op) } zv = zend_hash_index_find(zend_handlers_table, (zend_long)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); - op->handler = (const void *)(uintptr_t)Z_LVAL_P(zv); + op->handler = (zend_vm_opcode_handler_t)(uintptr_t)Z_LVAL_P(zv); } ZEND_API void ZEND_FASTCALL zend_deserialize_opcode_handler(zend_op *op) @@ -68210,9 +128633,7 @@ ZEND_API void ZEND_FASTCALL zend_deserialize_opcode_handler(zend_op *op) ZEND_API const void* ZEND_FASTCALL zend_get_opcode_handler_func(const zend_op *op) { -#if ZEND_VM_KIND == ZEND_VM_KIND_CALL - return op->handler; -#elif ZEND_VM_KIND == ZEND_VM_KIND_HYBRID +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL zval *zv; if (!zend_handlers_table) { @@ -68221,6 +128642,8 @@ ZEND_API const void* ZEND_FASTCALL zend_get_opcode_handler_func(const zend_op *o zv = zend_hash_index_find(zend_handlers_table, (zend_long)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; +#elif ZEND_VM_KIND == ZEND_VM_KIND_CALL + return op->handler; #else return NULL; #endif @@ -68285,15 +128708,15 @@ static uint32_t ZEND_FASTCALL zend_vm_get_opcode_handler_idx(uint32_t spec, cons return (spec & SPEC_START_MASK) + offset; } -#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC -static const void *zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op) +#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) || !ZEND_VM_SPEC +static zend_vm_opcode_handler_t zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op) { return zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)]; } #endif -#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID -static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op) +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +static zend_vm_opcode_handler_func_t zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op) { uint32_t spec = zend_spec_handlers[opcode]; return zend_opcode_handler_funcs[zend_vm_get_opcode_handler_idx(spec, op)]; @@ -68595,8 +129018,8 @@ ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex) { -#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) - opcode_handler_t handler; +#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) + zend_vm_opcode_handler_func_t handler; #endif DCL_OPLINE; int ret; @@ -68613,11 +129036,11 @@ ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex) LOAD_OPLINE(); #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) - handler = (opcode_handler_t)zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline); + handler = zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline); handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (EXPECTED(opline != &hybrid_halt_op)) { #else - ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + (OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (EXPECTED(opline)) { #endif ret = execute_data != ex ? (int)(execute_data->prev_execute_data != ex) + 1 : 0; @@ -68626,8 +129049,13 @@ ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex) ret = -1; } #else - opline = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) { +# if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + handler = zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline); + opline = handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +# else + opline = (OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +# endif + if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) { opline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT); if (EXPECTED(opline)) { /* ZEND_VM_ENTER() or ZEND_VM_LEAVE() */ diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 6fecd39346a70..53b1ac6baf0a3 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -7,7 +7,7 @@ # pragma GCC optimize("no-gcse") # pragma GCC optimize("no-ivopts") #endif -#ifdef _WIN64 +#if defined(_WIN64) && defined(_M_X64) /* See save_xmm_x86_64_ms_masm.asm */ void {%EXECUTOR_NAME%}_ex_real(zend_execute_data *ex) #else @@ -126,7 +126,7 @@ ZEND_API void ZEND_FASTCALL zend_serialize_opcode_handler(zend_op *op) } zv = zend_hash_index_find(zend_handlers_table, (zend_long)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); - op->handler = (const void *)(uintptr_t)Z_LVAL_P(zv); + op->handler = (zend_vm_opcode_handler_t)(uintptr_t)Z_LVAL_P(zv); } ZEND_API void ZEND_FASTCALL zend_deserialize_opcode_handler(zend_op *op) @@ -136,9 +136,7 @@ ZEND_API void ZEND_FASTCALL zend_deserialize_opcode_handler(zend_op *op) ZEND_API const void* ZEND_FASTCALL zend_get_opcode_handler_func(const zend_op *op) { -#if ZEND_VM_KIND == ZEND_VM_KIND_CALL - return op->handler; -#elif ZEND_VM_KIND == ZEND_VM_KIND_HYBRID +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL zval *zv; if (!zend_handlers_table) { @@ -147,6 +145,8 @@ ZEND_API const void* ZEND_FASTCALL zend_get_opcode_handler_func(const zend_op *o zv = zend_hash_index_find(zend_handlers_table, (zend_long)(uintptr_t)op->handler); ZEND_ASSERT(zv != NULL); return zend_opcode_handler_funcs[Z_LVAL_P(zv)]; +#elif ZEND_VM_KIND == ZEND_VM_KIND_CALL + return op->handler; #else return NULL; #endif diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index dbd7da0430f1c..01fe2999ab4aa 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -49,10 +49,11 @@ error_reporting(E_ALL); -const ZEND_VM_KIND_CALL = 1; -const ZEND_VM_KIND_SWITCH = 2; -const ZEND_VM_KIND_GOTO = 3; -const ZEND_VM_KIND_HYBRID = 4; +const ZEND_VM_KIND_CALL = 1; +const ZEND_VM_KIND_SWITCH = 2; +const ZEND_VM_KIND_GOTO = 3; +const ZEND_VM_KIND_HYBRID = 4; +const ZEND_VM_KIND_TAILCALL = 5; $vm_op_flags = array( "ZEND_VM_OP_SPEC" => 1<<0, @@ -142,6 +143,7 @@ ZEND_VM_KIND_SWITCH => "ZEND_VM_KIND_SWITCH", ZEND_VM_KIND_GOTO => "ZEND_VM_KIND_GOTO", ZEND_VM_KIND_HYBRID => "ZEND_VM_KIND_HYBRID", + ZEND_VM_KIND_TAILCALL => "ZEND_VM_KIND_TAILCALL", ); $op_types = array( @@ -543,24 +545,28 @@ $helpers = array(); // opcode helpers by name $params = array(); // parameters of helpers $opnames = array(); // opcode name to code mapping -$line_no = 1; +$line_nos = []; $used_extra_spec = array(); // Writes $s into resulting executor function out($f, $s) { - global $line_no; + global $line_nos; fputs($f,$s); - $line_no += substr_count($s, "\n"); + + $line_nos[(int)$f] ??= 1; + $line_nos[(int)$f] += substr_count($s, "\n"); } // Resets #line directives in resulting executor function out_line($f) { - global $line_no, $executor_file; + global $line_nos, $executor_file; + + $line_nos[(int)$f] ??= 1; + $line_nos[(int)$f]++; - fputs($f,"#line ".($line_no+1)." \"".$executor_file."\"\n"); - ++$line_no; + fputs($f,"#line ".$line_nos[(int)$f]." \"".$executor_file."\"\n"); } function is_hot_helper($name) { @@ -574,7 +580,7 @@ function is_hot_helper($name) { } // Returns name of specialized helper -function helper_name($name, $spec, $op1, $op2, $extra_spec) { +function helper_name($name, $spec, $op1, $op2, $extra_spec, $kind) { global $prefix, $helpers; $extra = ""; @@ -616,13 +622,15 @@ function helper_name($name, $spec, $op1, $op2, $extra_spec) { } } - return $name . ($spec ? "_SPEC" : "") . $prefix[$op1] . $prefix[$op2] . $extra; + $variant = $kind === ZEND_VM_KIND_TAILCALL ? '_TAILCALL' : ''; + return $name . ($spec ? "_SPEC" : "") . $prefix[$op1] . $prefix[$op2] . $extra . $variant; } -function opcode_name($name, $spec, $op1, $op2, $extra_spec) { +function opcode_name($name, $spec, $op1, $op2, $extra_spec, $kind) { global $prefix, $opnames, $opcodes; $extra = ""; + $variant = $kind === ZEND_VM_KIND_TAILCALL ? '_TAILCALL' : ''; if (isset($opnames[$name])) { $opcode = $opcodes[$opnames[$name]]; @@ -642,7 +650,7 @@ function opcode_name($name, $spec, $op1, $op2, $extra_spec) { $op1 = "ANY"; } else if ($spec) { /* dispatch to invalid handler from unreachable code */ - return "ZEND_NULL"; + return "ZEND_NULL$variant"; } } if (!isset($opcode["op2"][$op2])) { @@ -659,7 +667,7 @@ function opcode_name($name, $spec, $op1, $op2, $extra_spec) { $op2 = "ANY"; } else if ($spec) { /* dispatch to unknown handler in unreachable code */ - return "ZEND_NULL"; + return "ZEND_NULL$variant"; } } /* forward common specs (e.g. in ZEND_VM_DISPATCH_TO_HANDLER) */ @@ -668,7 +676,7 @@ function opcode_name($name, $spec, $op1, $op2, $extra_spec) { } } - return $name . ($spec ? "_SPEC" : "") . $prefix[$op1] . $prefix[$op2] . $extra; + return $name . ($spec ? "_SPEC" : "") . $prefix[$op1] . $prefix[$op2] . $extra . $variant; } // Formats condition, protecting it by parentheses when needed. @@ -732,8 +740,8 @@ function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null) "/FREE_OP2_IF_VAR\(\)/" => $op2_free_op_if_var[$op2], "/\!ZEND_VM_SPEC/m" => ($op1!="ANY"||$op2!="ANY"||$extra_spec)?"0":"1", "/ZEND_VM_SPEC/m" => ($op1!="ANY"||$op2!="ANY"||$extra_spec)?"1":"0", - "/ZEND_VM_C_LABEL\(\s*([A-Za-z_]*)\s*\)/m" => "\\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""), - "/ZEND_VM_C_GOTO\(\s*([A-Za-z_]*)\s*\)/m" => "goto \\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""), + "/ZEND_VM_C_LABEL\(\s*([A-Za-z_]*)\s*\)/m" => "\\1".(($spec && $kind != ZEND_VM_KIND_CALL && $kind != ZEND_VM_KIND_TAILCALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""), + "/ZEND_VM_C_GOTO\(\s*([A-Za-z_]*)\s*\)/m" => "goto \\1".(($spec && $kind != ZEND_VM_KIND_CALL && $kind != ZEND_VM_KIND_TAILCALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""), "/^#(\s*)if\s+1\s*\\|\\|.*[^\\\\]$/m" => "#\\1if 1", "/^#(\s*)if\s+0\s*&&.*[^\\\\]$/m" => "#\\1if 0", "/^#(\s*)elif\s+1\s*\\|\\|.*[^\\\\]$/m" => "#\\1elif 1", @@ -796,7 +804,7 @@ function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null) "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m", ), - function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) { + function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $kind) { if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) { return "execute_data"; } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) { @@ -804,35 +812,36 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) { $name = $matches[1]; $opcode = $opcodes[$opnames[$name]]; - return "goto " . opcode_name($name, $spec, $op1, $op2, $extra_spec) . "_LABEL"; + return "goto " . opcode_name($name, $spec, $op1, $op2, $extra_spec, $kind) . "_LABEL"; } else { // ZEND_VM_DISPATCH_TO_HELPER if (is_hot_helper($matches[1])) { if (isset($matches[2])) { // extra args $args = preg_replace("/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]); - return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL"; + return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "_LABEL"; } - return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL"; + return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "_LABEL"; } if (isset($matches[2])) { // extra args $args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2); - return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))"; + return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))"; } - return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; + return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; } }, $code); break; case ZEND_VM_KIND_CALL: + case ZEND_VM_KIND_TAILCALL: $code = preg_replace_callback( array( "/EXECUTE_DATA(?=[^_])/m", "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m", ), - function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $name) { + function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $name, $kind) { if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) { return "execute_data"; } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) { @@ -841,20 +850,24 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $name) { $handler = $matches[1]; $opcode = $opcodes[$opnames[$handler]]; $inline = - ZEND_VM_KIND == ZEND_VM_KIND_HYBRID && + ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID && isset($opcode["use"]) && is_hot_handler($opcode["hot"], $op1, $op2, $extra_spec) && is_hot_handler($opcodes[$opnames[$name]]["hot"], $op1, $op2, $extra_spec) ? "_INLINE" : ""; - return "ZEND_VM_TAIL_CALL(" . opcode_name($handler, $spec, $op1, $op2, $extra_spec) . $inline . "_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; + return "ZEND_VM_TAIL_CALL(" . opcode_name($handler, $spec, $op1, $op2, $extra_spec, $kind) . $inline . "_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; } else { // ZEND_VM_DISPATCH_TO_HELPER if (isset($matches[2])) { // extra args $args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2); - return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))"; + return "ZEND_VM_DISPATCH_TO_HELPER(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))"; + } + if ($kind === ZEND_VM_KIND_TAILCALL && $matches[1] === 'zend_leave_helper') { + return "ZEND_VM_DISPATCH_TO_LEAVE_HELPER(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . ")"; + } else { + return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; } - return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))"; } }, $code); @@ -866,19 +879,19 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $name) { "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m", ), - function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) { + function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $kind) { if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) { return "execute_data"; } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) { - return "goto " . opcode_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL"; + return "goto " . opcode_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "_LABEL"; } else { // ZEND_VM_DISPATCH_TO_HELPER if (isset($matches[2])) { // extra args $args = preg_replace("/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]); - return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec); + return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind); } - return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec); + return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind); } }, $code); @@ -890,19 +903,19 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) { "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m", ), - function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) { + function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $kind) { if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) { return "execute_data"; } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) { - return "goto " . opcode_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL"; + return "goto " . opcode_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind) . "_LABEL"; } else { // ZEND_VM_DISPATCH_TO_HELPER if (isset($matches[2])) { // extra args $args = preg_replace("/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]); - return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec); + return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind); } - return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec); + return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec, $kind); } }, $code); @@ -910,10 +923,7 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) { } /* Remove unnecessary ';' */ - $code = preg_replace('/^\s*;\s*$/m', '', $code); - - /* Remove WS */ - $code = preg_replace('/[ \t]+\n/m', "\n", $code); + $code = preg_replace('/^\s*;\s*$/m', "\n", $code); out($f, $code); } @@ -1047,7 +1057,8 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, // Generate opcode handler's entry point according to selected threading model $additional_func = false; - $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):""); + $variant = $kind === ZEND_VM_KIND_TAILCALL ? '_TAILCALL' : ''; + $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):"").$variant; switch ($kind) { case ZEND_VM_KIND_HYBRID: if (is_inline_hybrid_handler($name, $opcode["hot"], $op1, $op2, $extra_spec)) { @@ -1079,17 +1090,19 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, } return; case ZEND_VM_KIND_CALL: - if ($opcode["hot"] && ZEND_VM_KIND == ZEND_VM_KIND_HYBRID && is_hot_handler($opcode["hot"], $op1, $op2, $extra_spec)) { + case ZEND_VM_KIND_TAILCALL: + $cconv = $kind === ZEND_VM_KIND_TAILCALL ? 'ZEND_OPCODE_HANDLER_CCONV' : 'ZEND_OPCODE_HANDLER_FUNC_CCONV'; + if ($opcode["hot"] && ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID && is_hot_handler($opcode["hot"], $op1, $op2, $extra_spec)) { if (isset($opcode["use"])) { - out($f,"static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f,"static zend_always_inline ZEND_OPCODE_HANDLER_RET {$cconv} {$spec_name}_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); $additional_func = true; } else { - out($f,"static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f,"static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET {$cconv} {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); } } else if ($opcode["hot"] && is_cold_handler($opcode["hot"], $op1, $op2, $extra_spec)) { - out($f,"static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f,"static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET {$cconv} {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); } else { - out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET {$cconv} {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); } break; case ZEND_VM_KIND_SWITCH: @@ -1116,7 +1129,8 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec); if ($additional_func) { - out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + $cconv = $kind === ZEND_VM_KIND_TAILCALL ? 'ZEND_OPCODE_HANDLER_CCONV' : 'ZEND_OPCODE_HANDLER_FUNC_CCONV'; + out($f,"static ZEND_OPCODE_HANDLER_RET {$cconv} {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); out($f,"{\n"); out($f,"\tZEND_VM_TAIL_CALL({$spec_name}_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); out($f,"}\n"); @@ -1125,7 +1139,7 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, } // Generates helper -function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $inline, $cold = false, $hot = false, $extra_spec = null) { +function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $inline, $cold = false, $hot = false, $extra_spec = null, $signature_only = false) { global $definition_file, $prefix; if ($kind == ZEND_VM_KIND_HYBRID && !$hot) { @@ -1140,7 +1154,8 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, out($f, "#line $lineno \"$definition_file\"\n"); } - $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):""); + $variant = $kind === ZEND_VM_KIND_TAILCALL ? '_TAILCALL' : ''; + $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):"").$variant; // Generate helper's entry point according to selected threading model switch ($kind) { @@ -1148,8 +1163,11 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, out($f, $spec_name . "_LABEL:\n"); break; case ZEND_VM_KIND_CALL: + case ZEND_VM_KIND_TAILCALL: if ($inline) { $zend_attributes = " zend_always_inline"; + $zend_cconv = ""; + $zend_cconv_ex = ""; $zend_fastcall = ""; } else { if ($cold) { @@ -1157,14 +1175,22 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, } else { $zend_attributes = " zend_never_inline"; } - $zend_fastcall = " ZEND_FASTCALL"; + if ($kind !== ZEND_VM_KIND_TAILCALL) { + $zend_cconv = " ZEND_OPCODE_HANDLER_FUNC_CCONV "; + $zend_cconv_ex = " ZEND_OPCODE_HANDLER_FUNC_CCONV_EX "; + } else { + $zend_cconv = " ZEND_OPCODE_HANDLER_CCONV "; + $zend_cconv_ex = " ZEND_OPCODE_HANDLER_CCONV_EX "; + } + $zend_fastcall = " ZEND_FASTCALL "; } + $semi = $signature_only ? ';' : ''; if ($param == null) { // Helper without parameters - out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_cconv $spec_name(ZEND_OPCODE_HANDLER_ARGS)$semi\n"); } else { // Helper with parameter - out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS_EX $param)\n"); + out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_cconv_ex $spec_name(ZEND_OPCODE_HANDLER_ARGS_EX $param)$semi\n"); } break; case ZEND_VM_KIND_SWITCH: @@ -1175,18 +1201,22 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, break; } - // Generate helper's code - gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec); + if (!$signature_only) { + // Generate helper's code + gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec); + } } - function gen_null_label($f, $kind, $prolog) { switch ($kind) { case ZEND_VM_KIND_CALL: out($f,$prolog."ZEND_NULL_HANDLER,\n"); break; + case ZEND_VM_KIND_TAILCALL: + out($f,$prolog."ZEND_NULL_TAILCALL_HANDLER,\n"); + break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)-1,\n"); + out($f,$prolog."-1,\n"); break; case ZEND_VM_KIND_GOTO: out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n"); @@ -1387,8 +1417,11 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() case ZEND_VM_KIND_CALL: out($f,"$prolog{$spec_name}_HANDLER,\n"); break; + case ZEND_VM_KIND_TAILCALL: + out($f,"$prolog{$spec_name}_TAILCALL_HANDLER,\n"); + break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)$switch_labels[$spec_name],\n"); + out($f,$prolog."$switch_labels[$spec_name],\n"); break; case ZEND_VM_KIND_GOTO: out($f,$prolog."(void*)&&{$spec_name}_LABEL,\n"); @@ -1433,10 +1466,11 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() // to handler of undefined opcode switch ($kind) { case ZEND_VM_KIND_CALL: - out($f,$prolog."ZEND_NULL_HANDLER,\n"); + case ZEND_VM_KIND_TAILCALL: + out($f,$prolog."ZEND_NULL{$variant}_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)-1,\n"); + out($f,$prolog."-1,\n"); break; case ZEND_VM_KIND_GOTO: out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n"); @@ -1453,6 +1487,7 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() // Emit pointer to unspecialized handler switch ($kind) { case ZEND_VM_KIND_CALL: + case ZEND_VM_KIND_TAILCALL: out($f,$prolog.$dsc['alias']."_HANDLER,\n"); break; case ZEND_VM_KIND_GOTO: @@ -1464,10 +1499,11 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() // Emit pointer to unspecialized handler switch ($kind) { case ZEND_VM_KIND_CALL: + case ZEND_VM_KIND_TAILCALL: out($f,$prolog.$dsc["op"]."_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)".((string)$num).",\n"); + out($f,$prolog.((string)$num).",\n"); break; case ZEND_VM_KIND_GOTO: out($f,$prolog."(void*)&&".$dsc["op"]."_LABEL,\n"); @@ -1477,10 +1513,11 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() } else { switch ($kind) { case ZEND_VM_KIND_CALL: - out($f,$prolog."ZEND_NULL_HANDLER,\n"); + case ZEND_VM_KIND_TAILCALL: + out($f,$prolog."ZEND_NULL{$variant}_HANDLER,\n"); break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)-1,\n"); + out($f,$prolog."-1,\n"); break; case ZEND_VM_KIND_GOTO: out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n"); @@ -1496,8 +1533,11 @@ function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array() case ZEND_VM_KIND_CALL: out($f,$prolog."ZEND_NULL_HANDLER\n"); break; + case ZEND_VM_KIND_TAILCALL: + out($f,$prolog."ZEND_NULL_TAILCALL_HANDLER\n"); + break; case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)-1\n"); + out($f,$prolog."-1\n"); break; case ZEND_VM_KIND_GOTO: out($f,$prolog."(void*)&&ZEND_NULL_LABEL\n"); @@ -1533,22 +1573,24 @@ function gen_specs($f, $prolog, $specs) { } // Generates handler for undefined opcodes (CALL threading model) -function gen_null_handler($f) { - static $done = 0; - - // New and all executors with CALL threading model can use the same handler - // for undefined opcodes, do we emit code for it only once - if (!$done) { - $done = 1; - out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); - out($f,"{\n"); - out($f,"\tUSE_OPLINE\n"); - out($f,"\n"); - out($f,"\tSAVE_OPLINE();\n"); - out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n"); - out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n"); - out($f,"}\n\n"); - } +function gen_null_handler($f, $kind) { + $cconv = $kind === ZEND_VM_KIND_TAILCALL ? 'ZEND_OPCODE_HANDLER_CCONV' : 'ZEND_OPCODE_HANDLER_FUNC_CCONV'; + $variant = $kind === ZEND_VM_KIND_TAILCALL ? '_TAILCALL' : ''; + out($f,"static ZEND_OPCODE_HANDLER_RET {$cconv} ZEND_NULL{$variant}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f,"{\n"); + out($f,"\tUSE_OPLINE\n"); + out($f,"\n"); + out($f,"\tSAVE_OPLINE();\n"); + out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n"); + out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n"); + out($f,"}\n\n"); +} + +function gen_halt_handler($f, $kind) { + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HALT_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f,"{\n"); + out($f,"\treturn (zend_op*) ZEND_VM_ENTER_BIT;\n"); + out($f,"}\n\n"); } function extra_spec_name($extra_spec) { @@ -1671,6 +1713,8 @@ function read_order_file($fn) { function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) { global $list, $opcodes, $helpers, $op_types_ex, $gen_order; + $delayed_helpers = fopen("php://memory", "w+"); + if ($spec) { // Produce specialized executor $op1t = $op_types_ex; @@ -1698,7 +1742,13 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) if (isset($helpers[$num]["op1"][$op1]) && isset($helpers[$num]["op2"][$op2])) { // Generate helper code - gen_helper($f, 1, $kind, $num, $op1, $op2, $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"], $helpers[$num]["cold"], $helpers[$num]["hot"], $extra_spec); + if ($kind === ZEND_VM_KIND_TAILCALL && $helpers[$num]["param"] !== null) { + $out = $delayed_helpers; + gen_helper($f, 1, $kind, $num, $op1, $op2, $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"], $helpers[$num]["cold"], $helpers[$num]["hot"], $extra_spec, signature_only: true); + } else { + $out = $f; + } + gen_helper($out, 1, $kind, $num, $op1, $op2, $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"], $helpers[$num]["cold"], $helpers[$num]["hot"], $extra_spec); } } } else { @@ -1722,7 +1772,13 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) } else if (isset($dsc["helper"])) { $num = $dsc["helper"]; // Generate helper code - gen_helper($f, 0, $kind, $num, "ANY", "ANY", $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"], $helpers[$num]["cold"], $helpers[$num]["hot"]); + if ($kind === ZEND_VM_KIND_TAILCALL && $helpers[$num]["param"] !== null) { + $out = $delayed_helpers; + gen_helper($out, 0, $kind, $num, "ANY", "ANY", $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"], $helpers[$num]["cold"], $helpers[$num]["hot"], signature_only: true); + } else { + $out = $f; + } + gen_helper($out, 0, $kind, $num, "ANY", "ANY", $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"], $helpers[$num]["cold"], $helpers[$num]["hot"]); } else { var_dump($dsc); die("??? $kind:$num\n"); @@ -1746,7 +1802,11 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) // Generate handler for undefined opcodes switch ($kind) { case ZEND_VM_KIND_CALL: - gen_null_handler($f); + gen_null_handler($f, $kind); + break; + case ZEND_VM_KIND_TAILCALL: + gen_null_handler($f, $kind); + gen_halt_handler($f, $kind); break; case ZEND_VM_KIND_SWITCH: out($f,"default: ZEND_NULL_LABEL:\n"); @@ -1774,6 +1834,21 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) out($f,"\t\t\t\tHYBRID_BREAK(); /* Never reached */\n"); break; } + + rewind($delayed_helpers); + $delayed_helpers = stream_get_contents($delayed_helpers); + if ($delayed_helpers !== '') { + out($f, "/* The following helpers can not tailcall due to signature mismatch. Redefine some macros so they do not enforce tailcall. */\n"); + out($f, "#pragma push_macro(\"ZEND_VM_CONTINUE\")\n"); + out($f, "#undef ZEND_VM_CONTINUE\n"); + out($f, "#pragma push_macro(\"ZEND_VM_INTERRUPT\")\n"); + out($f, "#undef ZEND_VM_INTERRUPT\n"); + out($f, "#define ZEND_VM_CONTINUE(handler) return opline\n"); + out($f, "#define ZEND_VM_INTERRUPT() return zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)\n"); + out($f, $delayed_helpers); + out($f, "#pragma pop_macro(\"ZEND_VM_INTERRUPT\")\n"); + out($f, "#pragma pop_macro(\"ZEND_VM_CONTINUE\")\n"); + } } function skip_blanks($f, $prolog, $epilog) { @@ -1813,20 +1888,25 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define SPEC_RULE_OBSERVER 0x02000000\n"); out($f,"\n"); out($f,"static const uint32_t *zend_spec_handlers;\n"); - out($f,"static const void * const *zend_opcode_handlers;\n"); + out($f,"static zend_vm_opcode_handler_t const *zend_opcode_handlers;\n"); out($f,"static int zend_handlers_count;\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f,"static const void * const * zend_opcode_handler_funcs;\n"); + out($f,"static zend_vm_opcode_handler_func_t const * zend_opcode_handler_funcs;\n"); out($f,"static zend_op hybrid_halt_op;\n"); out($f,"#endif\n"); } - out($f,"#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC\n"); - out($f,"static const void *zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op);\n"); + if ($kind == ZEND_VM_KIND_HYBRID || $kind == ZEND_VM_KIND_CALL) { + out($f,"#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL\n\n"); + out($f,"static zend_vm_opcode_handler_func_t const * zend_opcode_handler_funcs;\n"); + out($f,"#endif\n"); + } + out($f,"#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) || !ZEND_VM_SPEC\n"); + out($f,"static zend_vm_opcode_handler_t zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op);\n"); out($f,"#endif\n\n"); if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f,"static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op);\n"); + out($f,"#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL\n"); + out($f,"static zend_vm_opcode_handler_func_t zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op);\n"); out($f,"#else\n"); out($f,"# define zend_vm_get_opcode_handler_func zend_vm_get_opcode_handler\n"); out($f,"#endif\n\n"); @@ -1882,11 +1962,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n"); out($f,"# define ZEND_OPCODE_HANDLER_RET void\n"); out($f,"# define ZEND_VM_TAIL_CALL(call) call; return\n"); - out($f,"# ifdef ZEND_VM_TAIL_CALL_DISPATCH\n"); - out($f,"# define ZEND_VM_CONTINUE() ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); return\n"); - out($f,"# else\n"); - out($f,"# define ZEND_VM_CONTINUE() return\n"); - out($f,"# endif\n"); + out($f,"# define ZEND_VM_CONTINUE() return\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,"# if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); out($f,"# define ZEND_VM_RETURN() opline = &hybrid_halt_op; return\n"); @@ -1911,8 +1987,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) } out($f,"# define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE\n"); out($f,"#endif\n"); - out($f,"\n"); - out($f,"typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"#define ZEND_VM_DISPATCH_TO_HELPER(call) ZEND_VM_TAIL_CALL(call)\n"); out($f,"\n"); out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n"); out($f,"# define DCL_OPLINE\n"); @@ -1952,13 +2027,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler_func(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler_func(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); } else { - out($f,"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n"); + out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); } out($f,"\n"); - out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);\n"); - out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n"); out($f,"\n"); break; case ZEND_VM_KIND_SWITCH: @@ -2034,13 +2109,57 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) // out($f,"# define ZEND_VM_INTERRUPT() goto zend_interrupt_helper_SPEC_LABEL\n"); out($f,"#endif\n\n"); } + + if ($kind == ZEND_VM_KIND_HYBRID || $kind == ZEND_VM_KIND_CALL) { + + /* Generate both CALL and TAILCALL handlers. + * TAILCALL handlers are used as zend_vm_opcode_handler_t + * when supported. + * CALL handlers are used as zend_vm_opcode_handler_func_t. + */ + out($f,"#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL\n"); + out($f,"\n"); + out($f,"# undef ZEND_VM_TAIL_CALL\n"); + out($f,"# undef ZEND_VM_CONTINUE\n"); + out($f,"# undef ZEND_VM_RETURN\n"); + out($f,"# undef ZEND_VM_DISPATCH_TO_HELPER\n"); + out($f,"# undef ZEND_VM_INTERRUPT\n"); + out($f,"\n"); + out($f,"# define ZEND_VM_TAIL_CALL(call) ZEND_MUSTTAIL return call\n"); + out($f,"# define ZEND_VM_CONTINUE() ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n"); + out($f,"# define ZEND_VM_RETURN() opline = &call_halt_op; ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_DISPATCH_TO_HELPER(call) \\\n"); + out($f," do { \\\n"); + out($f," opline = call; \\\n"); + out($f," ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); \\\n"); + out($f," } while (0)\n"); + out($f,"# define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE()\n"); + out($f,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n"); + out($f,"\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_HALT_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n"); + out($f,"static zend_never_inline const zend_op *ZEND_OPCODE_HANDLER_CCONV zend_leave_helper_SPEC_TAILCALL(zend_execute_data *ex, const zend_op *opline);\n"); + out($f,"\n"); + out($f,"static const zend_op call_halt_op = {\n"); + out($f," .handler = ZEND_HALT_TAILCALL_HANDLER,\n"); + out($f,"};\n"); + out($f,"static const zend_op call_leave_op = {\n"); + out($f," .handler = zend_leave_helper_SPEC_TAILCALL,\n"); + out($f,"};\n"); + out($f,"\n"); + + gen_executor_code($f, $spec, ZEND_VM_KIND_TAILCALL, $m[1]); + + out($f,"#endif /* ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL */\n"); + } break; case "EXECUTOR_NAME": out($f, $m[1].$executor_name.$m[3]."\n"); break; case "HELPER_VARS": if ($kind == ZEND_VM_KIND_SWITCH) { - out($f,$m[1]."const void *dispatch_handler;\n"); + out($f,$m[1]."zend_vm_opcode_handler_t dispatch_handler;\n"); } if ($kind != ZEND_VM_KIND_CALL && count($params)) { if ($kind == ZEND_VM_KIND_HYBRID) { @@ -2094,11 +2213,11 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) } $prolog = $m[1]; out($f,$prolog."if (UNEXPECTED(execute_data == NULL)) {\n"); - out($f,$prolog."\tstatic const void * const labels[] = {\n"); + out($f,$prolog."\tstatic zend_vm_opcode_handler_t const labels[] = {\n"); gen_labels($f, $spec, ($kind == ZEND_VM_KIND_HYBRID) ? ZEND_VM_KIND_GOTO : $kind, $prolog."\t\t", $specs); out($f,$prolog."\t};\n"); - out($f,$prolog."\tzend_opcode_handlers = (const void **) labels;\n"); - out($f,$prolog."\tzend_handlers_count = sizeof(labels) / sizeof(void*);\n"); + out($f,$prolog."\tzend_opcode_handlers = (zend_vm_opcode_handler_t*) labels;\n"); + out($f,$prolog."\tzend_handlers_count = sizeof(labels) / sizeof(labels[0]);\n"); if ($kind == ZEND_VM_KIND_HYBRID) { out($f,$prolog."\tmemset(&hybrid_halt_op, 0, sizeof(hybrid_halt_op));\n"); out($f,$prolog."\thybrid_halt_op.handler = (void*)&&HYBRID_HALT_LABEL;\n"); @@ -2143,10 +2262,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,"#else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n"); case ZEND_VM_KIND_CALL: out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n"); - out($f, $m[1]."((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f, $m[1]."(OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); out($f, $m[1]."if (UNEXPECTED(!OPLINE))".$m[3]."\n"); out($f,"#else\n"); - out($f, $m[1]."opline = ((opcode_handler_t)opline->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f, $m[1]."opline = (opline->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); out($f, $m[1]."if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT)))".$m[3]."\n"); out($f,"#endif\n"); if ($kind == ZEND_VM_KIND_HYBRID) { @@ -2194,7 +2313,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) break; case "EXTERNAL_EXECUTOR": if ($kind == ZEND_VM_KIND_CALL) { - gen_executor_code($f, $spec, $kind, $m[1]); + gen_executor_code($f, $spec, ZEND_VM_KIND_CALL, $m[1]); } break; case "INITIALIZER_NAME": @@ -2212,25 +2331,38 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,$prolog."zend_spec_handlers = specs;\n"); out($f,$prolog.$executor_name."_ex(NULL);\n"); } else { - out($f,$prolog."static const void * const labels[] = {\n"); - gen_labels($f, $spec, ($kind == ZEND_VM_KIND_HYBRID) ? ZEND_VM_KIND_CALL : $kind, $prolog."\t", $specs, $switch_labels); + out($f,$prolog."static zend_vm_opcode_handler_func_t const funcs[] = {\n"); + gen_labels($f, $spec, ZEND_VM_KIND_CALL, $prolog."\t", $specs); + out($f,$prolog."};\n"); + out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL || ZEND_VM_KIND == ZEND_VM_KIND_SWITCH\n"); + out($f,$prolog."static zend_vm_opcode_handler_t const handlers[] = {\n"); + gen_labels($f, $spec, $kind === ZEND_VM_KIND_HYBRID || $kind === ZEND_VM_KIND_CALL ? ZEND_VM_KIND_TAILCALL : $kind, $prolog."\t", $specs, $switch_labels); out($f,$prolog."};\n"); + out($f,$prolog."zend_handlers_count = sizeof(handlers) / sizeof(handlers[0]);\n"); + out($f, "#elif ZEND_VM_KIND != ZEND_VM_KIND_HYBRID\n"); + out($f,$prolog."static zend_vm_opcode_handler_t const *handlers = funcs;\n"); + out($f,$prolog."zend_handlers_count = sizeof(funcs) / sizeof(funcs[0]);\n"); + out($f, "#endif\n"); out($f,$prolog."static const uint32_t specs[] = {\n"); gen_specs($f, $prolog."\t", $specs); out($f,$prolog."};\n"); + out($f,"#if 0\n"); if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f,$prolog."zend_opcode_handler_funcs = labels;\n"); + out($f,"#elif (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); + out($f,$prolog."zend_opcode_handler_funcs = funcs;\n"); out($f,$prolog."zend_spec_handlers = specs;\n"); out($f,$prolog.$executor_name."_ex(NULL);\n"); - out($f,"#else\n"); } - out($f,$prolog."zend_opcode_handlers = labels;\n"); - out($f,$prolog."zend_handlers_count = sizeof(labels) / sizeof(void*);\n"); - out($f,$prolog."zend_spec_handlers = specs;\n"); - if ($kind == ZEND_VM_KIND_HYBRID) { - out($f,"#endif\n"); + if ($kind == ZEND_VM_KIND_HYBRID || $kind == ZEND_VM_KIND_CALL) { + out($f,"#elif ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL\n"); + out($f,$prolog."zend_opcode_handler_funcs = funcs;\n"); + out($f,$prolog."zend_opcode_handlers = handlers;\n"); + out($f,$prolog."zend_spec_handlers = specs;\n"); } + out($f,"#else\n"); + out($f,$prolog."zend_opcode_handlers = handlers;\n"); + out($f,$prolog."zend_spec_handlers = specs;\n"); + out($f,"#endif\n"); } break; default: @@ -2342,16 +2474,34 @@ function gen_vm_opcodes_header( $str .= "#define ZEND_VM_KIND_SWITCH\t" . ZEND_VM_KIND_SWITCH . "\n"; $str .= "#define ZEND_VM_KIND_GOTO\t" . ZEND_VM_KIND_GOTO . "\n"; $str .= "#define ZEND_VM_KIND_HYBRID\t" . ZEND_VM_KIND_HYBRID . "\n"; - if ($GLOBALS["vm_kind_name"][ZEND_VM_KIND] === "ZEND_VM_KIND_HYBRID") { + $str .= "#define ZEND_VM_KIND_TAILCALL\t" . ZEND_VM_KIND_TAILCALL . "\n"; + $str .= << $val) { $str .= sprintf("#define %-24s 0x%08x\n", $name, $val); } @@ -2579,9 +2753,9 @@ function gen_vm($def, $skel) { } // Store parameters - if ((ZEND_VM_KIND == ZEND_VM_KIND_GOTO - || ZEND_VM_KIND == ZEND_VM_KIND_SWITCH - || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID && $hot)) + if ((ZEND_VM_GEN_KIND == ZEND_VM_KIND_GOTO + || ZEND_VM_GEN_KIND == ZEND_VM_KIND_SWITCH + || (ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID && $hot)) && $param) { foreach (explode(",", $param ) as $p) { $p = trim($p); @@ -2643,7 +2817,7 @@ function gen_vm($def, $skel) { die("ERROR ($def:$lineno): Opcode with name '$op' is not defined.\n"); } $opcodes[$opnames[$dsc['op']]]['alias'] = $op; - if (!ZEND_VM_SPEC && ZEND_VM_KIND == ZEND_VM_KIND_SWITCH) { + if (!ZEND_VM_SPEC && ZEND_VM_GEN_KIND == ZEND_VM_KIND_SWITCH) { $code = $opnames[$op]; $opcodes[$code]['use'] = 1; } @@ -2669,46 +2843,46 @@ function gen_vm($def, $skel) { // Insert header out($f, HEADER_TEXT); - fputs($f,"#include \n"); - fputs($f,"#include \n"); - fputs($f,"#include \n\n"); + out($f,"#include \n"); + out($f,"#include \n"); + out($f,"#include \n\n"); - fputs($f,"static const char *zend_vm_opcodes_names[".($max_opcode + 1)."] = {\n"); + out($f,"static const char *zend_vm_opcodes_names[".($max_opcode + 1)."] = {\n"); for ($i = 0; $i <= $max_opcode; $i++) { - fputs($f,"\t".(isset($opcodes[$i]["op"])?'"'.$opcodes[$i]["op"].'"':"NULL").",\n"); + out($f,"\t".(isset($opcodes[$i]["op"])?'"'.$opcodes[$i]["op"].'"':"NULL").",\n"); } - fputs($f, "};\n\n"); + out($f, "};\n\n"); - fputs($f,"static uint32_t zend_vm_opcodes_flags[".($max_opcode + 1)."] = {\n"); + out($f,"static uint32_t zend_vm_opcodes_flags[".($max_opcode + 1)."] = {\n"); for ($i = 0; $i <= $max_opcode; $i++) { - fprintf($f, "\t0x%08x,\n", isset($opcodes[$i]["flags"]) ? $opcodes[$i]["flags"] : 0); - } - fputs($f, "};\n\n"); - - fputs($f, "ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) {\n"); - fputs($f, "\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n"); - fputs($f, "\t\treturn NULL;\n"); - fputs($f, "\t}\n"); - fputs($f, "\treturn zend_vm_opcodes_names[opcode];\n"); - fputs($f, "}\n"); - - fputs($f, "ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(uint8_t opcode) {\n"); - fputs($f, "\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n"); - fputs($f, "\t\topcode = ZEND_NOP;\n"); - fputs($f, "\t}\n"); - fputs($f, "\treturn zend_vm_opcodes_flags[opcode];\n"); - fputs($f, "}\n"); - - fputs($f, "ZEND_API uint8_t zend_get_opcode_id(const char *name, size_t length) {\n"); - fputs($f, "\tuint8_t opcode;\n"); - fputs($f, "\tfor (opcode = 0; opcode < (sizeof(zend_vm_opcodes_names) / sizeof(zend_vm_opcodes_names[0])) - 1; opcode++) {\n"); - fputs($f, "\t\tconst char *opcode_name = zend_vm_opcodes_names[opcode];\n"); - fputs($f, "\t\tif (opcode_name && strncmp(opcode_name, name, length) == 0) {\n"); - fputs($f, "\t\t\treturn opcode;\n"); - fputs($f, "\t\t}\n"); - fputs($f, "\t}\n"); - fputs($f, "\treturn ZEND_VM_LAST_OPCODE + 1;\n"); - fputs($f, "}\n"); + out($f, sprintf("\t0x%08x,\n", isset($opcodes[$i]["flags"]) ? $opcodes[$i]["flags"] : 0)); + } + out($f, "};\n\n"); + + out($f, "ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) {\n"); + out($f, "\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n"); + out($f, "\t\treturn NULL;\n"); + out($f, "\t}\n"); + out($f, "\treturn zend_vm_opcodes_names[opcode];\n"); + out($f, "}\n"); + + out($f, "ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(uint8_t opcode) {\n"); + out($f, "\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n"); + out($f, "\t\topcode = ZEND_NOP;\n"); + out($f, "\t}\n"); + out($f, "\treturn zend_vm_opcodes_flags[opcode];\n"); + out($f, "}\n"); + + out($f, "ZEND_API uint8_t zend_get_opcode_id(const char *name, size_t length) {\n"); + out($f, "\tuint8_t opcode;\n"); + out($f, "\tfor (opcode = 0; opcode < (sizeof(zend_vm_opcodes_names) / sizeof(zend_vm_opcodes_names[0])) - 1; opcode++) {\n"); + out($f, "\t\tconst char *opcode_name = zend_vm_opcodes_names[opcode];\n"); + out($f, "\t\tif (opcode_name && strncmp(opcode_name, name, length) == 0) {\n"); + out($f, "\t\t\treturn opcode;\n"); + out($f, "\t\t}\n"); + out($f, "\t}\n"); + out($f, "\treturn ZEND_VM_LAST_OPCODE + 1;\n"); + out($f, "}\n"); fclose($f); echo "zend_vm_opcodes.c generated successfully.\n"; @@ -2756,7 +2930,7 @@ function gen_vm($def, $skel) { out($f, "255\n};\n\n"); // Generate specialized executor - gen_executor($f, $skl, ZEND_VM_SPEC, ZEND_VM_KIND, "execute", "zend_vm_init"); + gen_executor($f, $skl, ZEND_VM_SPEC, ZEND_VM_GEN_KIND, "execute", "zend_vm_init"); out($f, "\n"); // Generate zend_vm_get_opcode_handler() function @@ -2839,8 +3013,8 @@ function gen_vm($def, $skel) { out($f, "\treturn (spec & SPEC_START_MASK) + offset;\n"); } out($f, "}\n\n"); - out($f, "#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC\n"); - out($f, "static const void *zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op)\n"); + out($f, "#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) || !ZEND_VM_SPEC\n"); + out($f, "static zend_vm_opcode_handler_t zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op)\n"); out($f, "{\n"); if (!ZEND_VM_SPEC) { out($f, "\treturn zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n"); @@ -2850,10 +3024,10 @@ function gen_vm($def, $skel) { out($f, "}\n"); out($f, "#endif\n\n"); - if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_GEN_KIND == ZEND_VM_KIND_CALL) { // Generate zend_vm_get_opcode_handler_func() function - out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID\n"); - out($f,"static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op)\n"); + out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL\n"); + out($f,"static zend_vm_opcode_handler_func_t zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op)\n"); out($f, "{\n"); out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n"); if (!ZEND_VM_SPEC) { @@ -2961,12 +3135,12 @@ function gen_vm($def, $skel) { out($f, "}\n\n"); // Generate zend_vm_call_opcode_handler() function - if (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_GEN_KIND == ZEND_VM_KIND_CALL || ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID) { out($f, "ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex)\n"); out($f, "{\n"); - if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { - out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f, "\topcode_handler_t handler;\n"); + if (ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID) { + out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL)\n"); + out($f, "\tzend_vm_opcode_handler_func_t handler;\n"); out($f,"#endif\n"); } out($f, "\tDCL_OPLINE;\n"); @@ -2983,15 +3157,15 @@ function gen_vm($def, $skel) { out($f, "\n"); out($f, "\tLOAD_OPLINE();\n"); out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n"); - if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID) { out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n"); - out($f, "\thandler = (opcode_handler_t)zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline);\n"); + out($f, "\thandler = zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline);\n"); out($f, "\thandler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); out($f, "\tif (EXPECTED(opline != &hybrid_halt_op)) {\n"); out($f,"#else\n"); } - out($f, "\t((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); - if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { + out($f, "\t(OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + if (ZEND_VM_GEN_KIND == ZEND_VM_KIND_HYBRID) { out($f, "\tif (EXPECTED(opline)) {\n"); out($f,"#endif\n"); } else { @@ -3003,9 +3177,14 @@ function gen_vm($def, $skel) { out($f, "\t\tret = -1;\n"); out($f, "\t}\n"); out($f, "#else\n"); - out($f, "\topline = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); - - out($f, "if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) {\n"); + out($f, "# if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL\n"); + out($f, "\thandler = zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline);\n"); + out($f, "\topline = handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f, "# else\n"); + out($f, "\topline = (OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"); + out($f, "# endif\n"); + + out($f, "\tif (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) {\n"); out($f, "\t\topline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT);\n"); out($f, "\t\tif (EXPECTED(opline)) {\n"); out($f, "\t\t\t/* ZEND_VM_ENTER() or ZEND_VM_LEAVE() */\n"); @@ -3069,16 +3248,16 @@ function usage() { $kind = substr($argv[$i], strlen("--with-vm-kind=")); switch ($kind) { case "CALL": - define("ZEND_VM_KIND", ZEND_VM_KIND_CALL); + define("ZEND_VM_GEN_KIND", ZEND_VM_KIND_CALL); break; case "SWITCH": - define("ZEND_VM_KIND", ZEND_VM_KIND_SWITCH); + define("ZEND_VM_GEN_KIND", ZEND_VM_KIND_SWITCH); break; case "GOTO": - define("ZEND_VM_KIND", ZEND_VM_KIND_GOTO); + define("ZEND_VM_GEN_KIND", ZEND_VM_KIND_GOTO); break; case "HYBRID": - define("ZEND_VM_KIND", ZEND_VM_KIND_HYBRID); + define("ZEND_VM_GEN_KIND", ZEND_VM_KIND_HYBRID); break; default: echo("ERROR: Invalid vm kind '$kind'\n"); @@ -3102,9 +3281,9 @@ function usage() { } // Using defaults -if (!defined("ZEND_VM_KIND")) { +if (!defined("ZEND_VM_GEN_KIND")) { // Using CALL threading by default - define("ZEND_VM_KIND", ZEND_VM_KIND_HYBRID); + define("ZEND_VM_GEN_KIND", ZEND_VM_KIND_HYBRID); } if (!defined("ZEND_VM_SPEC")) { // Using specialized executor by default diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 29469bb5f7dca..287dec375f3a9 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -29,9 +29,21 @@ #define ZEND_VM_KIND_SWITCH 2 #define ZEND_VM_KIND_GOTO 3 #define ZEND_VM_KIND_HYBRID 4 +#define ZEND_VM_KIND_TAILCALL 5 +static const char *const zend_vm_kind_name[] = { + NULL, + "ZEND_VM_KIND_CALL", + "ZEND_VM_KIND_SWITCH", + "ZEND_VM_KIND_GOTO", + "ZEND_VM_KIND_HYBRID", + "ZEND_VM_KIND_TAILCALL", +}; +#if 0 /* HYBRID requires support for computed GOTO and global register variables*/ -#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS)) +#elif (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS)) # define ZEND_VM_KIND ZEND_VM_KIND_HYBRID +#elif defined(HAVE_MUSTTAIL) && defined(HAVE_PRESERVE_NONE) && (defined(__x86_64__) || defined(__aarch64__)) +# define ZEND_VM_KIND ZEND_VM_KIND_TAILCALL #else # define ZEND_VM_KIND ZEND_VM_KIND_CALL #endif @@ -42,6 +54,30 @@ # endif #endif +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +# define ZEND_OPCODE_HANDLER_CCONV ZEND_PRESERVE_NONE +# define ZEND_OPCODE_HANDLER_CCONV_EX ZEND_FASTCALL +#elif ZEND_VM_KIND == ZEND_VM_KIND_CALL +# define ZEND_OPCODE_HANDLER_CCONV ZEND_FASTCALL +# define ZEND_OPCODE_HANDLER_CCONV_EX ZEND_FASTCALL +#endif +#define ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_FASTCALL +#define ZEND_OPCODE_HANDLER_FUNC_CCONV_EX ZEND_FASTCALL + +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID +typedef const void* zend_vm_opcode_handler_t; +typedef void (ZEND_FASTCALL *zend_vm_opcode_handler_func_t)(void); +#elif ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +typedef const struct _zend_op *(ZEND_OPCODE_HANDLER_CCONV *zend_vm_opcode_handler_t)(struct _zend_execute_data *execute_data, const struct _zend_op *opline); +typedef const struct _zend_op *(ZEND_OPCODE_HANDLER_FUNC_CCONV *zend_vm_opcode_handler_func_t)(struct _zend_execute_data *execute_data, const struct _zend_op *opline); +#elif ZEND_VM_KIND == ZEND_VM_KIND_SWITCH +typedef int zend_vm_opcode_handler_t; +#elif ZEND_VM_KIND == ZEND_VM_KIND_GOTO +typedef const void* zend_vm_opcode_handler_t; +#else +# error +#endif + #define ZEND_VM_OP_SPEC 0x00000001 #define ZEND_VM_OP_CONST 0x00000002 #define ZEND_VM_OP_TMPVAR 0x00000004 diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index cf363cd12595c..0c729755ff445 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -36,19 +36,21 @@ typedef struct _zend_weakmap_iterator { uint32_t ht_iter; } zend_weakmap_iterator; -/* EG(weakrefs) is a map from a key corresponding to a zend_object pointer to all the WeakReference and/or WeakMap entries relating to that pointer. +/* EG(weakrefs) is a map from a key corresponding to a zend_object pointer to all the WeakReference, WeakMap, and/or bare HashTable entries relating to that pointer. * * 1. For a single WeakReference, * the HashTable's corresponding value's tag is a ZEND_WEAKREF_TAG_REF and the pointer is a singleton WeakReference instance (zend_weakref *) for that zend_object pointer (from WeakReference::create()). * 2. For a single WeakMap, the HashTable's corresponding value's tag is a ZEND_WEAKREF_TAG_MAP and the pointer is a WeakMap instance (zend_weakmap *). - * 3. For multiple values associated with the same zend_object pointer, the HashTable entry's tag is a ZEND_WEAKREF_TAG_HT with a HashTable mapping - * tagged pointers of at most 1 WeakReference and 1 or more WeakMaps to the same tagged pointer. + * 3. For a single bare HashTable, the HashTable's corresponding value's tag is a ZEND_WEAKREF_TAG_BARE_HT and the pointer is a HashTable*. + * 4. For multiple values associated with the same zend_object pointer, the HashTable entry's tag is a ZEND_WEAKREF_TAG_HT with a HashTable mapping + * tagged pointers of at most 1 WeakReference and 1 or more WeakMap or bare HashTable to the same tagged pointer. * * ZEND_MM_ALIGNED_OFFSET_LOG2 is at least 2 on supported architectures (pointers to the objects in question are aligned to 4 bytes (1<<2) even on 32-bit systems), * i.e. the least two significant bits of the pointer can be used as a tag (ZEND_WEAKREF_TAG_*). */ -#define ZEND_WEAKREF_TAG_REF 0 -#define ZEND_WEAKREF_TAG_MAP 1 -#define ZEND_WEAKREF_TAG_HT 2 +#define ZEND_WEAKREF_TAG_REF 0 +#define ZEND_WEAKREF_TAG_MAP 1 +#define ZEND_WEAKREF_TAG_HT 2 +#define ZEND_WEAKREF_TAG_BARE_HT 3 #define ZEND_WEAKREF_GET_TAG(p) (((uintptr_t) (p)) & 3) #define ZEND_WEAKREF_GET_PTR(p) ((void *) (((uintptr_t) (p)) & ~3)) #define ZEND_WEAKREF_ENCODE(p, t) ((void *) (((uintptr_t) (p)) | (t))) @@ -72,8 +74,8 @@ static inline void zend_weakref_unref_single( zend_weakref *wr = ptr; wr->referent = NULL; } else { - /* unreferencing WeakMap entry (at ptr) with a key of object. */ - ZEND_ASSERT(tag == ZEND_WEAKREF_TAG_MAP); + /* unreferencing WeakMap or bare HashTable entry (at ptr) with a key of object. */ + ZEND_ASSERT(tag == ZEND_WEAKREF_TAG_MAP || tag == ZEND_WEAKREF_TAG_BARE_HT); zend_hash_index_del((HashTable *) ptr, zend_object_to_weakref_key(object)); } } @@ -136,8 +138,8 @@ static void zend_weakref_unregister(zend_object *object, void *payload, bool wea if (weakref_free) { zend_weakref_unref_single(ptr, tag, object); } else { - /* The optimization of skipping unref is only used in the destructor of WeakMap */ - ZEND_ASSERT(ZEND_WEAKREF_GET_TAG(payload) == ZEND_WEAKREF_TAG_MAP); + /* The optimization of skipping unref is used for zend_weakrefs_hash_clean_ex() */ + ZEND_ASSERT(ZEND_WEAKREF_GET_TAG(payload) == ZEND_WEAKREF_TAG_MAP || ZEND_WEAKREF_GET_TAG(payload) == ZEND_WEAKREF_TAG_BARE_HT); } return; } @@ -161,15 +163,17 @@ static void zend_weakref_unregister(zend_object *object, void *payload, bool wea zend_weakref_unref_single( ZEND_WEAKREF_GET_PTR(payload), ZEND_WEAKREF_GET_TAG(payload), object); } else { - /* The optimization of skipping unref is only used in the destructor of WeakMap */ - ZEND_ASSERT(ZEND_WEAKREF_GET_TAG(payload) == ZEND_WEAKREF_TAG_MAP); + /* The optimization of skipping unref is used for zend_weakrefs_hash_clean_ex() */ + ZEND_ASSERT(ZEND_WEAKREF_GET_TAG(payload) == ZEND_WEAKREF_TAG_MAP || ZEND_WEAKREF_GET_TAG(payload) == ZEND_WEAKREF_TAG_BARE_HT); } } +/* Insert 'pData' into bare HashTable 'ht', with the given 'key'. 'key' is + * weakly referenced. 'ht' is considered to be a bare HashTable, not a WeakMap. */ ZEND_API zval *zend_weakrefs_hash_add(HashTable *ht, zend_object *key, zval *pData) { zval *zv = zend_hash_index_add(ht, zend_object_to_weakref_key(key), pData); if (zv) { - zend_weakref_register(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_MAP)); + zend_weakref_register(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_BARE_HT)); } return zv; } @@ -177,17 +181,26 @@ ZEND_API zval *zend_weakrefs_hash_add(HashTable *ht, zend_object *key, zval *pDa ZEND_API zend_result zend_weakrefs_hash_del(HashTable *ht, zend_object *key) { zval *zv = zend_hash_index_find(ht, zend_object_to_weakref_key(key)); if (zv) { - zend_weakref_unregister(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_MAP), 1); + zend_weakref_unregister(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_BARE_HT), 1); return SUCCESS; } return FAILURE; } -ZEND_API void zend_weakrefs_hash_clean(HashTable *ht) { +static void zend_weakrefs_hash_clean_ex(HashTable *ht, int type) { zend_ulong obj_key; - ZEND_HASH_FOREACH_NUM_KEY(ht, obj_key) { - zend_weakrefs_hash_del(ht, zend_weakref_key_to_object(obj_key)); + ZEND_HASH_MAP_FOREACH_NUM_KEY(ht, obj_key) { + /* Optimization: Don't call zend_weakref_unref_single to free individual entries from ht when unregistering (which would do a hash table lookup, call zend_hash_index_del, and skip over any bucket collisions). + * Let freeing the corresponding values for WeakMap entries be done in zend_hash_clean, freeing objects sequentially. + * The performance difference is notable for larger WeakMaps with worse cache locality. */ + zend_weakref_unregister( + zend_weakref_key_to_object(obj_key), ZEND_WEAKREF_ENCODE(ht, type), 0); } ZEND_HASH_FOREACH_END(); + zend_hash_clean(ht); +} + +ZEND_API void zend_weakrefs_hash_clean(HashTable *ht) { + zend_weakrefs_hash_clean_ex(ht, ZEND_WEAKREF_TAG_BARE_HT); } void zend_weakrefs_init(void) { @@ -336,14 +349,7 @@ static zend_object *zend_weakmap_create_object(zend_class_entry *ce) static void zend_weakmap_free_obj(zend_object *object) { zend_weakmap *wm = zend_weakmap_from(object); - zend_ulong obj_key; - ZEND_HASH_MAP_FOREACH_NUM_KEY(&wm->ht, obj_key) { - /* Optimization: Don't call zend_weakref_unref_single to free individual entries from wm->ht when unregistering (which would do a hash table lookup, call zend_hash_index_del, and skip over any bucket collisions). - * Let freeing the corresponding values for WeakMap entries be done in zend_hash_destroy, freeing objects sequentially. - * The performance difference is notable for larger WeakMaps with worse cache locality. */ - zend_weakref_unregister( - zend_weakref_key_to_object(obj_key), ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP), 0); - } ZEND_HASH_FOREACH_END(); + zend_weakrefs_hash_clean_ex(&wm->ht, ZEND_WEAKREF_TAG_MAP); zend_hash_destroy(&wm->ht); zend_object_std_dtor(&wm->std); } @@ -547,6 +553,10 @@ HashTable *zend_weakmap_get_object_key_entry_gc(zend_object *object, zval **tabl ZEND_ASSERT(zv); zend_get_gc_buffer_add_ptr(gc_buffer, zv); zend_get_gc_buffer_add_obj(gc_buffer, &wm->std); + } else if (ZEND_WEAKREF_GET_TAG(tagged_ptr) == ZEND_WEAKREF_TAG_BARE_HT) { + /* Bare HashTables are intentionally ignored, since they are + * intended for internal usage by extensions and might not be + * collectable. */ } } ZEND_HASH_FOREACH_END(); } else if (tag == ZEND_WEAKREF_TAG_MAP) { @@ -555,6 +565,8 @@ HashTable *zend_weakmap_get_object_key_entry_gc(zend_object *object, zval **tabl ZEND_ASSERT(zv); zend_get_gc_buffer_add_ptr(gc_buffer, zv); zend_get_gc_buffer_add_obj(gc_buffer, &wm->std); + } else if (tag == ZEND_WEAKREF_TAG_BARE_HT) { + /* Bare HashTables are intentionally ignored (see above) */ } zend_get_gc_buffer_use(gc_buffer, table, n); @@ -581,6 +593,9 @@ HashTable *zend_weakmap_get_object_entry_gc(zend_object *object, zval **table, i zval *zv = zend_hash_index_find(&wm->ht, obj_key); ZEND_ASSERT(zv); zend_get_gc_buffer_add_ptr(gc_buffer, zv); + } else if (ZEND_WEAKREF_GET_TAG(tagged_ptr) == ZEND_WEAKREF_TAG_BARE_HT) { + /* Bare HashTables are intentionally ignored + * (see zend_weakmap_get_object_key_entry_gc) */ } } ZEND_HASH_FOREACH_END(); } else if (tag == ZEND_WEAKREF_TAG_MAP) { @@ -588,6 +603,9 @@ HashTable *zend_weakmap_get_object_entry_gc(zend_object *object, zval **table, i zval *zv = zend_hash_index_find(&wm->ht, obj_key); ZEND_ASSERT(zv); zend_get_gc_buffer_add_ptr(gc_buffer, zv); + } else if (tag == ZEND_WEAKREF_TAG_BARE_HT) { + /* Bare HashTables are intentionally ignored + * (see zend_weakmap_get_object_key_entry_gc) */ } zend_get_gc_buffer_use(gc_buffer, table, n); @@ -648,7 +666,7 @@ static void zend_weakmap_iterator_get_current_key(zend_object_iterator *obj_iter zend_string *string_key; zend_ulong num_key; - int key_type = zend_hash_get_current_key_ex(&wm->ht, &string_key, &num_key, pos); + zend_hash_key_type key_type = zend_hash_get_current_key_ex(&wm->ht, &string_key, &num_key, pos); if (key_type == HASH_KEY_NON_EXISTENT) { ZVAL_NULL(key); return; diff --git a/benchmark/generate_diff.php b/benchmark/generate_diff.php index 94c020df4b998..466a6ae0e1ed3 100644 --- a/benchmark/generate_diff.php +++ b/benchmark/generate_diff.php @@ -62,7 +62,7 @@ function formatDiff(?int $baseInstructions, int $headInstructions): string { } function find_benchmarked_commit_hash(string $repo, string $commitHash): ?string { - $repeat = 10; + $repeat = 100; while (true) { if ($repeat-- <= 0) { diff --git a/build/Makefile.global b/build/Makefile.global index 32605a203e188..16d57b54c8313 100644 --- a/build/Makefile.global +++ b/build/Makefile.global @@ -89,7 +89,7 @@ PHP_TEST_SHARED_EXTENSIONS = ` \ . $$i; $(top_srcdir)/build/shtool echo -n -- " -d zend_extension=$(top_builddir)/modules/$$dlname"; \ done; \ fi` -PHP_DEPRECATED_DIRECTIVES_REGEX = '^(magic_quotes_(gpc|runtime|sybase)?|(zend_)?extension(_debug)?(_ts)?|session\.sid_(length|bits_per_character))[\t\ ]*=' +PHP_DEPRECATED_DIRECTIVES_REGEX = '^[\t\ ]*(magic_quotes_(gpc|runtime|sybase)?|(zend_)?extension(_debug)?(_ts)?|session\.sid_(length|bits_per_character))[\t\ ]*=' test: all @if test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \ diff --git a/build/ax_check_compile_flag.m4 b/build/ax_check_compile_flag.m4 index 68fd43d5ddb09..54191c55353ee 100644 --- a/build/ax_check_compile_flag.m4 +++ b/build/ax_check_compile_flag.m4 @@ -34,14 +34,24 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 7 +#serial 11 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether the _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS - _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + if test x"m4_case(_AC_LANG, + [C], [$GCC], + [C++], [$GXX], + [Fortran], [$GFC], + [Fortran 77], [$G77], + [Objective C], [$GOBJC], + [Objective C++], [$GOBJCXX], + [no])" = xyes ; then + add_gnu_werror="-Werror" + fi + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1 $add_gnu_werror" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) diff --git a/build/gen_stub.php b/build/gen_stub.php index d9327b67d042f..8495f3612ce54 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -54,7 +54,7 @@ function processDirectory(string $dir, Context $context): array { ); foreach ($it as $file) { $pathName = $file->getPathName(); - if (preg_match('/\.stub\.php$/', $pathName)) { + if (substr($pathName, -9) === '.stub.php') { $pathNames[] = $pathName; } } @@ -84,7 +84,7 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = $legacyFile = "{$stubFilenameWithoutExtension}_legacy_arginfo.h"; $stubCode = file_get_contents($stubFile); - $stubHash = computeStubHash($stubCode); + $stubHash = sha1(str_replace("\r\n", "\n", $stubCode)); $oldStubHash = extractStubHash($arginfoFile); if ($stubHash === $oldStubHash && !$context->forceParse) { /* Stub file did not change, do not regenerate. */ @@ -153,10 +153,6 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = } } -function computeStubHash(string $stubCode): string { - return sha1(str_replace("\r\n", "\n", $stubCode)); -} - function extractStubHash(string $arginfoFile): ?string { if (!file_exists($arginfoFile)) { return null; @@ -361,79 +357,51 @@ public function isMixed(): bool { return $this->isBuiltin && $this->name === 'mixed'; } - public function toTypeCode(): string { - assert($this->isBuiltin); - switch ($this->name) { - case "bool": - return "_IS_BOOL"; - case "int": - return "IS_LONG"; - case "float": - return "IS_DOUBLE"; - case "string": - return "IS_STRING"; - case "array": - return "IS_ARRAY"; - case "object": - return "IS_OBJECT"; - case "void": - return "IS_VOID"; - case "callable": - return "IS_CALLABLE"; - case "mixed": - return "IS_MIXED"; - case "static": - return "IS_STATIC"; - case "never": - return "IS_NEVER"; - case "null": - return "IS_NULL"; - case "false": - return "IS_FALSE"; - case "true": - return "IS_TRUE"; - default: - throw new Exception("Not implemented: $this->name"); - } - } - - public function toTypeMask(): string { + private function toTypeInfo(): array { assert($this->isBuiltin); switch ($this->name) { case "null": - return "MAY_BE_NULL"; + return ["IS_NULL", "MAY_BE_NULL"]; case "false": - return "MAY_BE_FALSE"; + return ["IS_FALSE", "MAY_BE_FALSE"]; case "true": - return "MAY_BE_TRUE"; + return ["IS_TRUE", "MAY_BE_TRUE"]; case "bool": - return "MAY_BE_BOOL"; + return ["_IS_BOOL", "MAY_BE_BOOL"]; case "int": - return "MAY_BE_LONG"; + return ["IS_LONG", "MAY_BE_LONG"]; case "float": - return "MAY_BE_DOUBLE"; + return ["IS_DOUBLE", "MAY_BE_DOUBLE"]; case "string": - return "MAY_BE_STRING"; + return ["IS_STRING", "MAY_BE_STRING"]; case "array": - return "MAY_BE_ARRAY"; + return ["IS_ARRAY", "MAY_BE_ARRAY"]; case "object": - return "MAY_BE_OBJECT"; + return ["IS_OBJECT", "MAY_BE_OBJECT"]; case "callable": - return "MAY_BE_CALLABLE"; + return ["IS_CALLABLE", "MAY_BE_CALLABLE"]; case "mixed": - return "MAY_BE_ANY"; + return ["IS_MIXED", "MAY_BE_ANY"]; case "void": - return "MAY_BE_VOID"; + return ["IS_VOID", "MAY_BE_VOID"]; case "static": - return "MAY_BE_STATIC"; + return ["IS_STATIC", "MAY_BE_STATIC"]; case "never": - return "MAY_BE_NEVER"; + return ["IS_NEVER", "MAY_BE_NEVER"]; default: throw new Exception("Not implemented: $this->name"); } } + public function toTypeCode(): string { + return $this->toTypeInfo()[0]; + } + + public function toTypeMask(): string { + return $this->toTypeInfo()[1]; + } + public function toOptimizerTypeMaskForArrayKey(): string { assert($this->isBuiltin); @@ -898,13 +866,6 @@ public function getDeclarationName(): string; abstract class AbstractConstName implements VariableLikeName { - public function equals(AbstractConstName $const): bool - { - return $this->__toString() === $const->__toString(); - } - - abstract public function isClassConst(): bool; - public function isUnknown(): bool { return strtolower($this->__toString()) === "unknown"; @@ -922,11 +883,6 @@ public function __construct(?Name $namespace, string $const) $this->const = $const; } - public function isClassConst(): bool - { - return false; - } - public function isUnknown(): bool { $name = $this->__toString(); @@ -957,11 +913,6 @@ public function __construct(Name $class, string $const) $this->const = $const; } - public function isClassConst(): bool - { - return true; - } - public function __toString(): string { return $this->class->toString() . "::" . $this->const; @@ -1000,7 +951,6 @@ public function getArgInfoName(): string; public function getMethodSynopsisFilename(): string; public function getNameForAttributes(): string; public function __toString(): string; - public function isMethod(): bool; public function isConstructor(): bool; public function isDestructor(): bool; } @@ -1009,9 +959,6 @@ class FunctionName implements FunctionOrMethodName { private /* readonly */ Name $name; public function __construct(Name $name) { - if ($name->name === '_clone') { - $name = new Name('clone', $name->getAttributes()); - } $this->name = $name; } @@ -1063,10 +1010,6 @@ public function __toString(): string { return $this->name->toString(); } - public function isMethod(): bool { - return false; - } - public function isConstructor(): bool { return false; } @@ -1112,10 +1055,6 @@ public function __toString(): string { return "$this->className::$this->methodName"; } - public function isMethod(): bool { - return true; - } - public function isConstructor(): bool { return $this->methodName === "__construct"; } @@ -1247,6 +1186,119 @@ private function beginArgInfoCompatible(string $funcInfoName, int $minArgs): str } } +class VersionFlags { + + /** + * Keys are the PHP versions, values are arrays of flags + */ + private array $flagsByVersion; + + public function __construct(array $baseFlags) { + $this->flagsByVersion = []; + foreach (ALL_PHP_VERSION_IDS as $version) { + $this->flagsByVersion[$version] = $baseFlags; + } + } + + public function addForVersionsAbove(string $flag, int $minimumVersionId): void { + $write = false; + + foreach (ALL_PHP_VERSION_IDS as $version) { + if ($version === $minimumVersionId || $write === true) { + $this->flagsByVersion[$version][] = $flag; + $write = true; + } + } + } + + public function isEmpty(): bool { + foreach (ALL_PHP_VERSION_IDS as $version) { + if ($this->flagsByVersion[$version] !== []) { + return false; + } + } + return true; + } + + public function generateVersionDependentFlagCode( + string $codeTemplate, + ?int $phpVersionIdMinimumCompatibility, + ?int $phpVersionIdMaxCompatibility = null + ): string { + $flagsByPhpVersions = $this->flagsByVersion; + $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])); + } + + ksort($flagsByPhpVersions); + // Remove flags which depend on a PHP version below the minimally supported one + $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); + if ($phpVersionIdMaxCompatibility !== null) { + // Remove flags which depend on a PHP version above the maximally supported one + $index = array_search($phpVersionIdMaxCompatibility, array_keys($flagsByPhpVersions)); + if ($index === false) { + throw new Exception("Missing version dependent flags for PHP version ID \"$phpVersionIdMaxCompatibility\""); + } + $flagsByPhpVersions = array_slice($flagsByPhpVersions, 0, $index, true); + } + + // Remove version-specific flags which don't differ from the previous one + // Also populate '0' values + $previousVersionId = null; + foreach ($flagsByPhpVersions as $versionId => $versionFlags) { + if ($versionFlags === []) { + $versionFlags = ['0']; + $flagsByPhpVersions[$versionId] = ['0']; + } + 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 + $code = ''; + $i = 0; + foreach (array_reverse($flagsByPhpVersions, true) as $version => $versionFlags) { + $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; + + $i++; + } + + return $code; + } +} + class FuncInfo { public /* readonly */ FunctionOrMethodName $name; private /* readonly */ int $classFlags; @@ -1317,10 +1369,10 @@ public function __construct( public function isMethod(): bool { - return $this->name->isMethod(); + return $this->name instanceof MethodName; } - public function isFinalMethod(): bool + private function isFinalMethod(): bool { return ($this->flags & Modifiers::FINAL) || ($this->classFlags & Modifiers::FINAL); } @@ -1331,7 +1383,7 @@ public function isInstanceMethod(): bool } /** @return string[] */ - public function getModifierNames(): array + private function getModifierNames(): array { if (!$this->isMethod()) { return []; @@ -1371,7 +1423,7 @@ private function hasParamWithUnknownDefaultValue(): bool return false; } - public function equalsApartFromNameAndRefcount(FuncInfo $other): bool { + private function equalsApartFromNameAndRefcount(FuncInfo $other): bool { if (count($this->args) !== count($other->args)) { return false; } @@ -1414,27 +1466,21 @@ public function getFramelessDeclaration(): ?string { return null; } - $php84MinimumCompatibility = $this->minimumPhpVersionIdCompatibility === null || $this->minimumPhpVersionIdCompatibility >= PHP_84_VERSION_ID; - $code = ''; - - if (!$php84MinimumCompatibility) { - $code .= "#if (PHP_VERSION_ID >= " . PHP_84_VERSION_ID . ")\n"; - } - + $infos = ''; foreach ($this->framelessFunctionInfos as $framelessFunctionInfo) { $code .= "ZEND_FRAMELESS_FUNCTION({$this->name->getFunctionName()}, {$framelessFunctionInfo->arity});\n"; + $infos .= "\t{ ZEND_FRAMELESS_FUNCTION_NAME({$this->name->getFunctionName()}, {$framelessFunctionInfo->arity}), {$framelessFunctionInfo->arity} },\n"; } $code .= 'static const zend_frameless_function_info ' . $this->getFramelessFunctionInfosName() . "[] = {\n"; - foreach ($this->framelessFunctionInfos as $framelessFunctionInfo) { - $code .= "\t{ ZEND_FRAMELESS_FUNCTION_NAME({$this->name->getFunctionName()}, {$framelessFunctionInfo->arity}), {$framelessFunctionInfo->arity} },\n"; - } + $code .= $infos; $code .= "\t{ 0 },\n"; $code .= "};\n"; + $php84MinimumCompatibility = $this->minimumPhpVersionIdCompatibility === null || $this->minimumPhpVersionIdCompatibility >= PHP_84_VERSION_ID; if (!$php84MinimumCompatibility) { - $code .= "#endif\n"; + return "#if (PHP_VERSION_ID >= " . PHP_84_VERSION_ID . ")\n$code#endif\n"; } return $code; @@ -1445,14 +1491,6 @@ private function getFramelessFunctionInfosName(): string { } public function getFunctionEntry(): string { - $code = ""; - - $php84MinimumCompatibility = $this->minimumPhpVersionIdCompatibility === null || $this->minimumPhpVersionIdCompatibility >= PHP_84_VERSION_ID; - $isVanillaEntry = $this->alias === null && !$this->supportsCompileTimeEval && $this->exposedDocComment === null && empty($this->framelessFunctionInfos); - $argInfoName = $this->getArgInfoName(); - $flagsByPhpVersions = $this->getArginfoFlagsByPhpVersions(); - $functionEntryCode = null; - if (!empty($this->framelessFunctionInfos)) { if ($this->isMethod()) { throw new Exception('Frameless methods are not supported yet'); @@ -1465,6 +1503,10 @@ public function getFunctionEntry(): string { } } + $isVanillaEntry = $this->alias === null && !$this->supportsCompileTimeEval && $this->exposedDocComment === null && empty($this->framelessFunctionInfos); + $argInfoName = $this->getArgInfoName(); + $flagsByPhpVersions = $this->getArginfoFlagsByPhpVersions(); + if ($this->isMethod()) { $zendName = '"' . $this->name->methodName . '"'; if ($this->alias) { @@ -1475,80 +1517,60 @@ public function getFunctionEntry(): string { } else { throw new Error("Cannot happen"); } + } elseif ($this->flags & Modifiers::ABSTRACT) { + $name = "NULL"; } else { - if ($this->flags & Modifiers::ABSTRACT) { - $name = "NULL"; - } else { - $name = "zim_" . $this->name->getDeclarationClassName() . "_" . $this->name->methodName; - - if ($isVanillaEntry) { - $template = "\tZEND_ME(" . $this->name->getDeclarationClassName() . ", " . $this->name->methodName . ", $argInfoName, %s)\n"; - $flagsCode = generateVersionDependentFlagCode( - $template, - $flagsByPhpVersions, - $this->minimumPhpVersionIdCompatibility - ); - $functionEntryCode = rtrim($flagsCode); - } + $name = "zim_" . $this->name->getDeclarationClassName() . "_" . $this->name->methodName; + + if ($isVanillaEntry) { + $template = "\tZEND_ME(" . $this->name->getDeclarationClassName() . ", " . $this->name->methodName . ", $argInfoName, %s)\n"; + $flagsCode = $flagsByPhpVersions->generateVersionDependentFlagCode( + $template, + $this->minimumPhpVersionIdCompatibility + ); + return rtrim($flagsCode) . "\n"; } } } else if ($this->name instanceof FunctionName) { $functionName = $this->name->getFunctionName(); $declarationName = $this->alias ? $this->alias->getNonNamespacedName() : $this->name->getDeclarationName(); + $name = "zif_$declarationName"; if ($this->name->getNamespace()) { $namespace = addslashes($this->name->getNamespace()); $zendName = "ZEND_NS_NAME(\"$namespace\", \"$functionName\")"; - $name = "zif_$declarationName"; } else { - $zendName = '"' . $functionName . '"'; - $name = "zif_$declarationName"; - // Can only use ZEND_FE() if we have no flags for *all* versions - $hasFlags = false; - foreach ($flagsByPhpVersions as $flags) { - if ($flags !== ['0']) { - $hasFlags = true; - break; - } - } - if ($isVanillaEntry && !$hasFlags) { - $functionEntryCode = "\tZEND_FE($declarationName, $argInfoName)"; + if ($isVanillaEntry && $flagsByPhpVersions->isEmpty()) { + return "\tZEND_FE($declarationName, $argInfoName)\n"; } + $zendName = '"' . $functionName . '"'; } } else { throw new Error("Cannot happen"); } - if ($functionEntryCode !== null) { - $code .= "$functionEntryCode\n"; - } else { - if (!$php84MinimumCompatibility) { - $code .= "#if (PHP_VERSION_ID >= " . PHP_84_VERSION_ID . ")\n"; - } - - $php84AndAboveFlags = array_slice($flagsByPhpVersions, 5, null, true); - $docComment = $this->exposedDocComment ? '"' . $this->exposedDocComment->escape() . '"' : "NULL"; - $framelessFuncInfosName = !empty($this->framelessFunctionInfos) ? $this->getFramelessFunctionInfosName() : "NULL"; + $docComment = $this->exposedDocComment ? '"' . $this->exposedDocComment->escape() . '"' : "NULL"; + $framelessFuncInfosName = !empty($this->framelessFunctionInfos) ? $this->getFramelessFunctionInfosName() : "NULL"; - $code .= generateVersionDependentFlagCode( - "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s, $framelessFuncInfosName, $docComment)\n", - $php84AndAboveFlags, - PHP_84_VERSION_ID - ); + // Assume 8.4+ here, if older versions are supported this is conditional + $code = $flagsByPhpVersions->generateVersionDependentFlagCode( + "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s, $framelessFuncInfosName, $docComment)\n", + PHP_84_VERSION_ID + ); - if (!$php84MinimumCompatibility) { - $code .= "#else\n"; + $php84MinimumCompatibility = $this->minimumPhpVersionIdCompatibility === null || $this->minimumPhpVersionIdCompatibility >= PHP_84_VERSION_ID; + if (!$php84MinimumCompatibility) { + $code = "#if (PHP_VERSION_ID >= " . PHP_84_VERSION_ID . ")\n$code"; + $code .= "#else\n"; - $flags = array_slice($flagsByPhpVersions, 0, 4, true); - $code .= generateVersionDependentFlagCode( - "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s)\n", - $flags, - $this->minimumPhpVersionIdCompatibility - ); + $code .= $flagsByPhpVersions->generateVersionDependentFlagCode( + "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s)\n", + $this->minimumPhpVersionIdCompatibility, + PHP_83_VERSION_ID + ); - $code .= "#endif\n"; - } + $code .= "#endif\n"; } return $code; @@ -1589,8 +1611,7 @@ public function discardInfoForOldPhpVersions(?int $minimumPhpVersionIdCompatibil $this->minimumPhpVersionIdCompatibility = $minimumPhpVersionIdCompatibility; } - /** @return array */ - private function getArginfoFlagsByPhpVersions(): array + private function getArginfoFlagsByPhpVersions(): VersionFlags { $flags = []; @@ -1628,39 +1649,21 @@ private function getArginfoFlagsByPhpVersions(): array } } - $php82AndAboveFlags = $flags; + $flags = new VersionFlags($flags); + if ($this->isMethod() === false && $this->supportsCompileTimeEval) { - $php82AndAboveFlags[] = "ZEND_ACC_COMPILE_TIME_EVAL"; + $flags->addForVersionsAbove("ZEND_ACC_COMPILE_TIME_EVAL", PHP_82_VERSION_ID); } - $php85AndAboveFlags = $php82AndAboveFlags; foreach ($this->attributes as $attr) { switch ($attr->class) { case "NoDiscard": - $php85AndAboveFlags[] = "ZEND_ACC_NODISCARD"; + $flags->addForVersionsAbove("ZEND_ACC_NODISCARD", PHP_85_VERSION_ID); break; } } - if (empty($flags)) { - $flags[] = "0"; - } - if (empty($php82AndAboveFlags)) { - $php82AndAboveFlags[] = "0"; - } - if (empty($php85AndAboveFlags)) { - $php85AndAboveFlags[] = "0"; - } - - return [ - PHP_70_VERSION_ID => $flags, - PHP_80_VERSION_ID => $flags, - PHP_81_VERSION_ID => $flags, - PHP_82_VERSION_ID => $php82AndAboveFlags, - PHP_83_VERSION_ID => $php82AndAboveFlags, - PHP_84_VERSION_ID => $php82AndAboveFlags, - PHP_85_VERSION_ID => $php85AndAboveFlags, - ]; + return $flags; } private function generateRefSect1(DOMDocument $doc, string $role): DOMElement { @@ -2358,11 +2361,14 @@ private function __construct($value, SimpleType $type, Expr $expr, array $origin $this->isUnknownConstValue = $isUnknownConstValue; } - public function initializeZval(string $zvalName): string + public function initializeZval(string $zvalName, bool $alreadyExists = false, string $forStringDef = ''): string { $cExpr = $this->getCExpr(); - $code = "\tzval $zvalName;\n"; + $code = ''; + if (!$alreadyExists) { + $code = "\tzval $zvalName;\n"; + } if ($this->type->isNull()) { $code .= "\tZVAL_NULL(&$zvalName);\n"; @@ -2382,8 +2388,11 @@ public function initializeZval(string $zvalName): string if ($cExpr === '""') { $code .= "\tZVAL_EMPTY_STRING(&$zvalName);\n"; } else { - $code .= "\tzend_string *{$zvalName}_str = zend_string_init($cExpr, strlen($cExpr), 1);\n"; - $code .= "\tZVAL_STR(&$zvalName, {$zvalName}_str);\n"; + if ($forStringDef === '') { + $forStringDef = "{$zvalName}_str"; + } + $code .= "\tzend_string *$forStringDef = zend_string_init($cExpr, strlen($cExpr), 1);\n"; + $code .= "\tZVAL_STR(&$zvalName, $forStringDef);\n"; } } elseif ($this->type->isArray()) { if ($cExpr == '[]') { @@ -2454,10 +2463,7 @@ abstract protected function getFieldSynopsisValueString(array $allConstInfos): ? abstract public function discardInfoForOldPhpVersions(?int $minimumPhpVersionIdCompatibility): void; - /** - * @return array - */ - protected function getFlagsByPhpVersion(): array + protected function getFlagsByPhpVersion(): VersionFlags { $flags = "ZEND_ACC_PUBLIC"; if ($this->flags & Modifiers::PROTECTED) { @@ -2466,15 +2472,7 @@ protected function getFlagsByPhpVersion(): array $flags = "ZEND_ACC_PRIVATE"; } - return [ - PHP_70_VERSION_ID => [$flags], - PHP_80_VERSION_ID => [$flags], - PHP_81_VERSION_ID => [$flags], - PHP_82_VERSION_ID => [$flags], - PHP_83_VERSION_ID => [$flags], - PHP_84_VERSION_ID => [$flags], - PHP_85_VERSION_ID => [$flags], - ]; + return new VersionFlags([$flags]); } protected function getTypeCode(string $variableLikeName, string &$code): string @@ -2575,23 +2573,6 @@ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fie } } - /** - * @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 @@ -2688,41 +2669,35 @@ protected function getFieldSynopsisValueString(array $allConstInfos): ?string return $this->valueString; } - public function getPredefinedConstantTerm(DOMDocument $doc, int $indentationLevel): DOMElement { + private function getPredefinedConstantElement( + DOMDocument $doc, + int $indentationLevel, + string $name + ): DOMElement { $indentation = str_repeat(" ", $indentationLevel); - $termElement = $doc->createElement("term"); + $element = $doc->createElement($name); $constantElement = $doc->createElement("constant"); $constantElement->textContent = $this->name->__toString(); $typeElement = ($this->phpDocType ?? $this->type)->getTypeForDoc($doc); - $termElement->appendChild(new DOMText("\n$indentation ")); - $termElement->appendChild($constantElement); - $termElement->appendChild(new DOMText("\n$indentation (")); - $termElement->appendChild($typeElement); - $termElement->appendChild(new DOMText(")\n$indentation")); + $element->appendChild(new DOMText("\n$indentation ")); + $element->appendChild($constantElement); + $element->appendChild(new DOMText("\n$indentation (")); + $element->appendChild($typeElement); + $element->appendChild(new DOMText(")\n$indentation")); - return $termElement; + return $element; } - public function getPredefinedConstantEntry(DOMDocument $doc, int $indentationLevel): DOMElement { - $indentation = str_repeat(" ", $indentationLevel); - - $entryElement = $doc->createElement("entry"); - - $constantElement = $doc->createElement("constant"); - $constantElement->textContent = $this->name->__toString(); - $typeElement = ($this->phpDocType ?? $this->type)->getTypeForDoc($doc); - - $entryElement->appendChild(new DOMText("\n$indentation ")); - $entryElement->appendChild($constantElement); - $entryElement->appendChild(new DOMText("\n$indentation (")); - $entryElement->appendChild($typeElement); - $entryElement->appendChild(new DOMText(")\n$indentation")); + public function getPredefinedConstantTerm(DOMDocument $doc, int $indentationLevel): DOMElement { + return $this->getPredefinedConstantElement($doc, $indentationLevel, "term"); + } - return $entryElement; + public function getPredefinedConstantEntry(DOMDocument $doc, int $indentationLevel): DOMElement { + return $this->getPredefinedConstantElement($doc, $indentationLevel, "entry"); } public function discardInfoForOldPhpVersions(?int $phpVersionIdMinimumCompatibility): void { @@ -2754,7 +2729,7 @@ public function getDeclaration(array $allConstInfos): string // Condition will be added by generateCodeWithConditions() - if ($this->name->isClassConst()) { + if ($this->name instanceof ClassConstName) { $code = $this->getClassConstDeclaration($value, $allConstInfos); } else { $code = $this->getGlobalConstDeclaration($value); @@ -2781,24 +2756,36 @@ private function getGlobalConstDeclaration(EvaluatedValue $value): string if ($this->isDeprecated) { $flags .= " | CONST_DEPRECATED"; } + + $code = "\t"; + if ($this->attributes !== []) { + if ($this->phpVersionIdMinimumCompatibility === null || $this->phpVersionIdMinimumCompatibility >= PHP_85_VERSION_ID) { + // Registration only returns the constant since PHP 8.5, it's + // not worth the bloat to add two different registration blocks + // with conditions for the PHP version + $constVarName = 'const_' . $constName; + $code .= "zend_constant *$constVarName = "; + } + } + if ($value->type->isNull()) { - return "\tREGISTER_NULL_CONSTANT(\"$constName\", $flags);\n"; + return $code . "REGISTER_NULL_CONSTANT(\"$constName\", $flags);\n"; } if ($value->type->isBool()) { - return "\tREGISTER_BOOL_CONSTANT(\"$constName\", " . ($cExpr ?: ($constValue ? "true" : "false")) . ", $flags);\n"; + return $code . "REGISTER_BOOL_CONSTANT(\"$constName\", " . ($cExpr ?: ($constValue ? "true" : "false")) . ", $flags);\n"; } if ($value->type->isInt()) { - return "\tREGISTER_LONG_CONSTANT(\"$constName\", " . ($cExpr ?: (int) $constValue) . ", $flags);\n"; + return $code . "REGISTER_LONG_CONSTANT(\"$constName\", " . ($cExpr ?: (int) $constValue) . ", $flags);\n"; } if ($value->type->isFloat()) { - return "\tREGISTER_DOUBLE_CONSTANT(\"$constName\", " . ($cExpr ?: (float) $constValue) . ", $flags);\n"; + return $code . "REGISTER_DOUBLE_CONSTANT(\"$constName\", " . ($cExpr ?: (float) $constValue) . ", $flags);\n"; } if ($value->type->isString()) { - return "\tREGISTER_STRING_CONSTANT(\"$constName\", " . ($cExpr ?: '"' . addslashes($constValue) . '"') . ", $flags);\n"; + return $code . "REGISTER_STRING_CONSTANT(\"$constName\", " . ($cExpr ?: '"' . addslashes($constValue) . '"') . ", $flags);\n"; } throw new Exception("Unimplemented constant type"); @@ -2809,7 +2796,8 @@ private function getClassConstDeclaration(EvaluatedValue $value, array $allConst { $constName = $this->name->getDeclarationName(); - $zvalCode = $value->initializeZval("const_{$constName}_value", $allConstInfos); + // TODO $allConstInfos is unused + $zvalCode = $value->initializeZval("const_{$constName}_value"); $code = "\n" . $zvalCode; @@ -2840,9 +2828,8 @@ private function getClassConstDeclaration(EvaluatedValue $value, array $allConst } $template .= "zend_declare_typed_class_constant(class_entry, $nameCode, &const_{$constName}_value, %s, $commentCode, $typeCode);\n"; - $code .= generateVersionDependentFlagCode( + $code .= $this->getFlagsByPhpVersion()->generateVersionDependentFlagCode( $template, - $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ); } @@ -2858,9 +2845,8 @@ private function getClassConstDeclaration(EvaluatedValue $value, array $allConst $template = "\t"; } $template .= "zend_declare_class_constant_ex(class_entry, $nameCode, &const_{$constName}_value, %s, $commentCode);\n"; - $code .= generateVersionDependentFlagCode( + $code .= $this->getFlagsByPhpVersion()->generateVersionDependentFlagCode( $template, - $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ); } @@ -2910,20 +2896,17 @@ private function getValueAssertion(EvaluatedValue $value): string throw new Exception("Unimplemented constant type"); } - /** - * @return array - */ - protected function getFlagsByPhpVersion(): array + protected function getFlagsByPhpVersion(): VersionFlags { $flags = parent::getFlagsByPhpVersion(); // $this->isDeprecated also accounts for any #[\Deprecated] attributes if ($this->isDeprecated) { - $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_DEPRECATED", PHP_80_VERSION_ID); + $flags->addForVersionsAbove("ZEND_ACC_DEPRECATED", PHP_80_VERSION_ID); } if ($this->flags & Modifiers::FINAL) { - $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_FINAL", PHP_81_VERSION_ID); + $flags->addForVersionsAbove("ZEND_ACC_FINAL", PHP_81_VERSION_ID); } return $flags; @@ -2943,14 +2926,7 @@ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fie } } -class PropertyInfo extends VariableLike -{ - private /* readonly */ int $classFlags; - public /* readonly */ PropertyName $name; - private /* readonly */ ?Expr $defaultValue; - private /* readonly */ ?string $defaultValueString; - private /* readonly */ bool $isDocReadonly; - private /* readonly */ bool $isVirtual; +class StringBuilder { // Map possible variable names to the known string constant, see // ZEND_KNOWN_STRINGS @@ -3053,8 +3029,90 @@ class PropertyInfo extends VariableLike "username" => "ZEND_STR_USERNAME", "password" => "ZEND_STR_PASSWORD", "clone" => "ZEND_STR_CLONE", + '8.0' => 'ZEND_STR_8_DOT_0', + '8.1' => 'ZEND_STR_8_DOT_1', + '8.2' => 'ZEND_STR_8_DOT_2', + '8.3' => 'ZEND_STR_8_DOT_3', + '8.4' => 'ZEND_STR_8_DOT_4', + '8.5' => 'ZEND_STR_8_DOT_5', ]; + /** + * Get an array of three strings: + * - declaration of zend_string, if needed, or empty otherwise + * - usage of that zend_string, or usage with ZSTR_KNOWN() + * - freeing the zend_string, if needed + * + * @param string $varName + * @param string $strContent + * @param ?int $minPHPCompatibility + * @param bool $interned + * @return string[] + */ + public static function getString( + string $varName, + string $content, + ?int $minPHPCompatibility, + bool $interned = false + ): array { + // Generally strings will not be known + $initFn = $interned ? 'zend_string_init_interned' : 'zend_string_init'; + $result = [ + "\tzend_string *$varName = $initFn(\"$content\", sizeof(\"$content\") - 1, 1);\n", + $varName, + "\tzend_string_release($varName);\n" + ]; + // For attribute values that are not freed + if ($varName === '') { + $result[0] = "$initFn(\"$content\", sizeof(\"$content\") - 1, 1);\n"; + } + // If not set, use the current latest version + $allVersions = ALL_PHP_VERSION_IDS; + $minPhp = $minPHPCompatibility ?? end($allVersions); + if ($minPhp < PHP_80_VERSION_ID) { + // No known strings in 7.0 + return $result; + } + $include = self::PHP_80_KNOWN; + switch ($minPhp) { + case PHP_85_VERSION_ID: + $include = array_merge($include, self::PHP_85_KNOWN); + // Intentional fall through + + case PHP_84_VERSION_ID: + $include = array_merge($include, self::PHP_84_KNOWN); + // Intentional fall through + + case PHP_83_VERSION_ID: + case PHP_82_VERSION_ID: + $include = array_merge($include, self::PHP_82_KNOWN); + // Intentional fall through + + case PHP_81_VERSION_ID: + $include = array_merge($include, self::PHP_81_KNOWN); + break; + } + if (array_key_exists($content, $include)) { + $knownStr = $include[$content]; + return [ + '', + "ZSTR_KNOWN($knownStr)", + '', + ]; + } + return $result; + } +} + +class PropertyInfo extends VariableLike +{ + private /* readonly */ int $classFlags; + public /* readonly */ PropertyName $name; + private /* readonly */ ?Expr $defaultValue; + private /* readonly */ ?string $defaultValueString; + private /* readonly */ bool $isDocReadonly; + private /* readonly */ bool $isVirtual; + /** * @param AttributeInfo[] $attributes */ @@ -3135,7 +3193,11 @@ public function getDeclaration(array $allConstInfos): string { $code .= $defaultValue->initializeZval($zvalName); } - [$stringInit, $nameCode, $stringRelease] = $this->getString($propertyName); + [$stringInit, $nameCode, $stringRelease] = StringBuilder::getString( + "property_{$propertyName}_name", + $propertyName, + $this->phpVersionIdMinimumCompatibility + ); $code .= $stringInit; if ($this->exposedDocComment) { @@ -3159,9 +3221,8 @@ public function getDeclaration(array $allConstInfos): string { $template .= "zend_declare_property_ex(class_entry, $nameCode, &$zvalName, %s, $commentCode);\n"; } - $code .= generateVersionDependentFlagCode( + $code .= $this->getFlagsByPhpVersion()->generateVersionDependentFlagCode( $template, - $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ); @@ -3170,83 +3231,26 @@ public function getDeclaration(array $allConstInfos): string { return $code; } - /** - * Get an array of three strings: - * - declaration of zend_string, if needed, or empty otherwise - * - usage of that zend_string, or usage with ZSTR_KNOWN() - * - freeing the zend_string, if needed - * - * @param string $propName - * @return string[] - */ - private function getString(string $propName): array { - // Generally strings will not be known - $nameCode = "property_{$propName}_name"; - $result = [ - "\tzend_string *$nameCode = zend_string_init(\"$propName\", sizeof(\"$propName\") - 1, 1);\n", - $nameCode, - "\tzend_string_release($nameCode);\n" - ]; - // If not set, use the current latest version - $allVersions = ALL_PHP_VERSION_IDS; - $minPhp = $this->phpVersionIdMinimumCompatibility ?? end($allVersions); - if ($minPhp < PHP_80_VERSION_ID) { - // No known strings in 7.0 - return $result; - } - $include = self::PHP_80_KNOWN; - switch ($minPhp) { - case PHP_85_VERSION_ID: - $include = array_merge($include, self::PHP_85_KNOWN); - // Intentional fall through - - case PHP_84_VERSION_ID: - $include = array_merge($include, self::PHP_84_KNOWN); - // Intentional fall through - - case PHP_83_VERSION_ID: - case PHP_82_VERSION_ID: - $include = array_merge($include, self::PHP_82_KNOWN); - // Intentional fall through - - case PHP_81_VERSION_ID: - $include = array_merge($include, self::PHP_81_KNOWN); - break; - } - if (array_key_exists($propName, $include)) { - $knownStr = $include[$propName]; - return [ - '', - "ZSTR_KNOWN($knownStr)", - '', - ]; - } - return $result; - } - - /** - * @return array - */ - protected function getFlagsByPhpVersion(): array + protected function getFlagsByPhpVersion(): VersionFlags { $flags = parent::getFlagsByPhpVersion(); if ($this->flags & Modifiers::STATIC) { - $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_STATIC", PHP_70_VERSION_ID); + $flags->addForVersionsAbove("ZEND_ACC_STATIC", PHP_70_VERSION_ID); } if ($this->flags & Modifiers::FINAL) { - $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_FINAL", PHP_84_VERSION_ID); + $flags->addForVersionsAbove("ZEND_ACC_FINAL", PHP_84_VERSION_ID); } if ($this->flags & Modifiers::READONLY) { - $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_READONLY", PHP_81_VERSION_ID); + $flags->addForVersionsAbove("ZEND_ACC_READONLY", PHP_81_VERSION_ID); } elseif ($this->classFlags & Modifiers::READONLY) { - $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_READONLY", PHP_82_VERSION_ID); + $flags->addForVersionsAbove("ZEND_ACC_READONLY", PHP_82_VERSION_ID); } if ($this->isVirtual) { - $flags = $this->addFlagForVersionsAbove($flags, "ZEND_ACC_VIRTUAL", PHP_84_VERSION_ID); + $flags->addForVersionsAbove("ZEND_ACC_VIRTUAL", PHP_84_VERSION_ID); } return $flags; @@ -3312,42 +3316,66 @@ public function __construct(string $class, array $args) { $this->args = $args; } - /** @param array $allConstInfos */ - public function generateCode(string $invocation, string $nameSuffix, array $allConstInfos, ?int $phpVersionIdMinimumCompatibility): string { - $php82MinimumCompatibility = $phpVersionIdMinimumCompatibility === null || $phpVersionIdMinimumCompatibility >= PHP_82_VERSION_ID; - $php84MinimumCompatibility = $phpVersionIdMinimumCompatibility === null || $phpVersionIdMinimumCompatibility >= PHP_84_VERSION_ID; - /* see ZEND_KNOWN_STRINGS in Zend/strings.h */ - $knowns = [ - "message" => "ZEND_STR_MESSAGE", - ]; - if ($php82MinimumCompatibility) { - $knowns["SensitiveParameter"] = "ZEND_STR_SENSITIVEPARAMETER"; - } - if ($php84MinimumCompatibility) { - $knowns["Deprecated"] = "ZEND_STR_DEPRECATED_CAPITALIZED"; - $knowns["since"] = "ZEND_STR_SINCE"; - } - - $code = "\n"; + /** + * @param array $allConstInfos + * @param array &$declaredStrings Map of string content to + * the name of a zend_string already created with that content + */ + public function generateCode(string $invocation, string $nameSuffix, array $allConstInfos, ?int $phpVersionIdMinimumCompatibility, array &$declaredStrings = []): string { $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"; - } + [$stringInit, $nameCode, $stringRelease] = StringBuilder::getString( + "attribute_name_{$escapedAttributeName}_$nameSuffix", + addcslashes($this->class, "\\"), + $phpVersionIdMinimumCompatibility, + true + ); + $code = "\n"; + $code .= $stringInit; + $code .= "\t" . ($this->args ? "zend_attribute *attribute_{$escapedAttributeName}_$nameSuffix = " : "") . "$invocation, $nameCode, " . count($this->args) . ");\n"; + $code .= $stringRelease; + foreach ($this->args as $i => $arg) { - $value = EvaluatedValue::createFromExpression($arg->value, null, null, $allConstInfos); - $zvalName = "attribute_{$escapedAttributeName}_{$nameSuffix}_arg$i"; - $code .= $value->initializeZval($zvalName); - $code .= "\tZVAL_COPY_VALUE(&attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value, &$zvalName);\n"; + $initValue = ''; + if ($arg->value instanceof Node\Scalar\String_) { + $strVal = $arg->value->value; + [$strInit, $strUse, $strRelease] = StringBuilder::getString( + 'unused', + $strVal, + $phpVersionIdMinimumCompatibility + ); + if ($strInit === '') { + $initValue = "\tZVAL_STR(&attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value, $strUse);\n"; + } elseif (isset($declaredStrings[$strVal])) { + $strUse = $declaredStrings[$strVal]; + $initValue = "\tZVAL_STR_COPY(&attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value, $strUse);\n"; + } + } + if ($initValue === '') { + $value = EvaluatedValue::createFromExpression($arg->value, null, null, $allConstInfos); + $code .= $value->initializeZval( + "attribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].value", + true, + "attribute_{$escapedAttributeName}_{$nameSuffix}_arg{$i}_str" + ); + if ($arg->value instanceof Node\Scalar\String_) { + $declaredStrings[$arg->value->value] = "attribute_{$escapedAttributeName}_{$nameSuffix}_arg{$i}_str"; + } + } else { + $code .= $initValue; + } if ($arg->name) { - if (isset($knowns[$arg->name->name])) { - $code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = ZSTR_KNOWN({$knowns[$arg->name->name]});\n"; + [$stringInit, $nameCode, $stringRelease] = StringBuilder::getString( + "", + $arg->name->name, + $phpVersionIdMinimumCompatibility, + true + ); + if ($stringInit === '') { + $nameCode .= ";\n"; } else { - $code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = zend_string_init_interned(\"{$arg->name->name}\", sizeof(\"{$arg->name->name}\") - 1, 1);\n"; + $nameCode = $stringInit; } + $code .= "\tattribute_{$escapedAttributeName}_{$nameSuffix}->args[$i].name = $nameCode"; } } return $code; @@ -3480,13 +3508,17 @@ public function getRegistration(array $allConstInfos): string $code .= "{\n"; + $flags = $this->getFlagsByPhpVersion(); + $classMethods = ($this->funcInfos === []) ? 'NULL' : "class_{$escapedName}_methods"; if ($this->type === "enum") { $name = addslashes((string) $this->name); $backingType = $this->enumBackingType ? $this->enumBackingType->toTypeCode() : "IS_UNDEF"; $code .= "\tzend_class_entry *class_entry = zend_register_internal_enum(\"$name\", $backingType, $classMethods);\n"; - $code .= generateVersionDependentFlagCode("\tclass_entry->ce_flags = %s;\n", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility); + if (!$flags->isEmpty()) { + $code .= $this->getFlagsByPhpVersion()->generateVersionDependentFlagCode("\tclass_entry->ce_flags = %s;\n", $this->phpVersionIdMinimumCompatibility); + } } else { $code .= "\tzend_class_entry ce, *class_entry;\n\n"; if (count($this->name->getParts()) > 1) { @@ -3504,7 +3536,7 @@ public function getRegistration(array $allConstInfos): string } $template = "\tclass_entry = zend_register_internal_class_with_flags(&ce, " . (isset($this->extends[0]) ? "class_entry_" . str_replace("\\", "_", $this->extends[0]->toString()) : "NULL") . ", %s);\n"; - $entries = generateVersionDependentFlagCode($template, $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility ? max($this->phpVersionIdMinimumCompatibility, PHP_84_VERSION_ID) : null); + $entries = $flags->generateVersionDependentFlagCode($template, $this->phpVersionIdMinimumCompatibility ? max($this->phpVersionIdMinimumCompatibility, PHP_84_VERSION_ID) : null); if ($entries !== '') { $code .= $entries; } else { @@ -3515,12 +3547,16 @@ public function getRegistration(array $allConstInfos): string $code .= "#else\n"; $code .= "\tclass_entry = zend_register_internal_class_ex(&ce, " . (isset($this->extends[0]) ? "class_entry_" . str_replace("\\", "_", $this->extends[0]->toString()) : "NULL") . ");\n"; - $code .= generateVersionDependentFlagCode("\tclass_entry->ce_flags |= %s;\n", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility); + if (!$flags->isEmpty()) { + $code .= $flags->generateVersionDependentFlagCode("\tclass_entry->ce_flags |= %s;\n", $this->phpVersionIdMinimumCompatibility); + } $code .= "#endif\n"; } } else { $code .= "\tclass_entry = zend_register_internal_interface(&ce);\n"; - $code .= generateVersionDependentFlagCode("\tclass_entry->ce_flags |= %s;\n", $this->getFlagsByPhpVersion(), $this->phpVersionIdMinimumCompatibility); + if (!$flags->isEmpty()) { + $code .= $flags->generateVersionDependentFlagCode("\tclass_entry->ce_flags |= %s;\n", $this->phpVersionIdMinimumCompatibility); + } } } @@ -3565,60 +3601,49 @@ function (Name $item) { foreach ($this->propertyInfos as $property) { $code .= $property->getDeclaration($allConstInfos); } + // Reusable strings for wrapping conditional PHP 8.0+ code + if ($php80MinimumCompatibility) { + $php80CondStart = ''; + $php80CondEnd = ''; + } else { + $php80CondStart = "\n#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")"; + $php80CondEnd = "#endif\n"; + } + + $declaredStrings = []; if (!empty($this->attributes)) { - if (!$php80MinimumCompatibility) { - $code .= "\n#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")"; - } + $code .= $php80CondStart; foreach ($this->attributes as $key => $attribute) { $code .= $attribute->generateCode( "zend_add_class_attribute(class_entry", "class_{$escapedName}_$key", $allConstInfos, - $this->phpVersionIdMinimumCompatibility + $this->phpVersionIdMinimumCompatibility, + $declaredStrings ); } - if (!$php80MinimumCompatibility) { - $code .= "#endif\n"; - } + $code .= $php80CondEnd; } - if ($attributeInitializationCode = generateConstantAttributeInitialization($this->constInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $this->cond)) { - if (!$php80MinimumCompatibility) { - $code .= "#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")"; - } - + if ($attributeInitializationCode = generateConstantAttributeInitialization($this->constInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $this->cond, $declaredStrings)) { + $code .= $php80CondStart; $code .= "\n" . $attributeInitializationCode; - - if (!$php80MinimumCompatibility) { - $code .= "#endif\n"; - } + $code .= $php80CondEnd; } - if ($attributeInitializationCode = generatePropertyAttributeInitialization($this->propertyInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility)) { - if (!$php80MinimumCompatibility) { - $code .= "#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")"; - } - + if ($attributeInitializationCode = generatePropertyAttributeInitialization($this->propertyInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $declaredStrings)) { + $code .= $php80CondStart; $code .= "\n" . $attributeInitializationCode; - - if (!$php80MinimumCompatibility) { - $code .= "#endif\n"; - } + $code .= $php80CondEnd; } - if ($attributeInitializationCode = generateFunctionAttributeInitialization($this->funcInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $this->cond)) { - if (!$php80MinimumCompatibility) { - $code .= "#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")\n"; - } - + if ($attributeInitializationCode = generateFunctionAttributeInitialization($this->funcInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $this->cond, $declaredStrings)) { + $code .= $php80CondStart; $code .= "\n" . $attributeInitializationCode; - - if (!$php80MinimumCompatibility) { - $code .= "#endif\n"; - } + $code .= $php80CondEnd; } $code .= "\n\treturn class_entry;\n"; @@ -3636,10 +3661,7 @@ function (Name $item) { return $code; } - /** - * @return array - */ - private function getFlagsByPhpVersion(): array + private function getFlagsByPhpVersion(): VersionFlags { $php70Flags = []; @@ -3659,44 +3681,28 @@ private function getFlagsByPhpVersion(): array $php70Flags[] = "ZEND_ACC_DEPRECATED"; } - $php80Flags = $php70Flags; + $flags = new VersionFlags($php70Flags); if ($this->isStrictProperties) { - $php80Flags[] = "ZEND_ACC_NO_DYNAMIC_PROPERTIES"; + $flags->addForVersionsAbove("ZEND_ACC_NO_DYNAMIC_PROPERTIES", PHP_80_VERSION_ID); } - $php81Flags = $php80Flags; - if ($this->isNotSerializable) { - $php81Flags[] = "ZEND_ACC_NOT_SERIALIZABLE"; + $flags->addForVersionsAbove("ZEND_ACC_NOT_SERIALIZABLE", PHP_81_VERSION_ID); } - $php82Flags = $php81Flags; - if ($this->flags & Modifiers::READONLY) { - $php82Flags[] = "ZEND_ACC_READONLY_CLASS"; + $flags->addForVersionsAbove("ZEND_ACC_READONLY_CLASS", PHP_82_VERSION_ID); } foreach ($this->attributes as $attr) { if ($attr->class === "AllowDynamicProperties") { - $php82Flags[] = "ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES"; + $flags->addForVersionsAbove("ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES", PHP_82_VERSION_ID); break; } } - $php83Flags = $php82Flags; - $php84Flags = $php83Flags; - $php85Flags = $php84Flags; - - return [ - PHP_70_VERSION_ID => $php70Flags, - PHP_80_VERSION_ID => $php80Flags, - PHP_81_VERSION_ID => $php81Flags, - PHP_82_VERSION_ID => $php82Flags, - PHP_83_VERSION_ID => $php83Flags, - PHP_84_VERSION_ID => $php84Flags, - PHP_85_VERSION_ID => $php85Flags, - ]; + return $flags; } public function discardInfoForOldPhpVersions(?int $phpVersionIdMinimumCompatibility): void { @@ -4308,13 +4314,25 @@ protected function pName_FullyQualified(Name\FullyQualified $node): string { $stmts = $parser->parse($code); $nodeTraverser->traverse($stmts); - $fileTags = DocCommentTag::parseDocComments(getFileDocComments($stmts)); + $fileTags = DocCommentTag::parseDocComments(self::getFileDocComments($stmts)); $fileInfo = new FileInfo($fileTags); $fileInfo->handleStatements($stmts, $prettyPrinter); return $fileInfo; } + /** @return DocComment[] */ + private static function getFileDocComments(array $stmts): array { + if (empty($stmts)) { + return []; + } + + return array_filter( + $stmts[0]->getComments(), + static fn ($comment): bool => $comment instanceof DocComment + ); + } + private function handleStatements(array $stmts, PrettyPrinterAbstract $prettyPrinter): void { $conds = []; foreach ($stmts as $stmt) { @@ -4486,6 +4504,17 @@ private static function handlePreprocessorConditions(array &$conds, Stmt $stmt): return empty($conds) ? null : implode(' && ', $conds); } + + /** @param array $allConstInfos */ + public function generateClassEntryCode(array $allConstInfos): string { + $code = ""; + + foreach ($this->classInfos as $class) { + $code .= "\n" . $class->getRegistration($allConstInfos); + } + + return $code; + } } class DocCommentTag { @@ -4533,7 +4562,7 @@ public function getVariableName(): string { if ($this->name === "param") { // Allow for parsing extended types like callable(string):mixed in docblocks - preg_match('/^\s*(?[\w\|\\\\]+(?\((?(?:(?&parens)|[^(){}[\]]*+))++\)|\{(?&inparens)\}|\[(?&inparens)\])*+(?::(?&type))?)\s*\$(?\w+).*$/', $value, $matches); + preg_match('/^\s*(?[\w\|\\\\]+(?\((?(?:(?&parens)|[^(){}[\]<>]*+))++\)|\{(?&inparens)\}|\[(?&inparens)\]|<(?&inparens)>)*+(?::(?&type))?)\s*\$(?\w+).*$/', $value, $matches); } elseif ($this->name === "prefer-ref") { preg_match('/^\s*\$(?\w+).*$/', $value, $matches); } @@ -4845,7 +4874,32 @@ function parseConstLike( } if ($type === null && $phpDocType === null) { - throw new Exception("Missing type for constant " . $name->__toString()); + if ($const->value instanceof Node\Scalar\Float_) { + $phpDocType = 'float'; + } elseif ($const->value instanceof Node\Scalar\Int_ + || ($const->value instanceof Expr\UnaryMinus + && $const->value->expr instanceof Node\Scalar\Int_ + ) + ) { + $phpDocType = 'int'; + } elseif ($const->value instanceof Node\Scalar\String_) { + $phpDocType = 'string'; + } elseif ($const->value instanceof Expr\ConstFetch + && $const->value->name instanceof Node\Name\FullyQualified + && ( + $const->value->name->name === 'false' + || $const->value->name->name === 'true' + ) + ) { + $phpDocType = 'bool'; + } elseif ($const->value instanceof Expr\ConstFetch + && $const->value->name instanceof Node\Name\FullyQualified + && $const->value->name->name === 'null' + ) { + $phpDocType = 'null'; + } else { + throw new Exception("Missing type for constant " . $name->__toString()); + } } $constType = $type ? Type::fromNode($type) : null; @@ -5039,18 +5093,6 @@ function parseClass( ); } -/** @return DocComment[] */ -function getFileDocComments(array $stmts): array { - if (empty($stmts)) { - return []; - } - - return array_filter( - $stmts[0]->getComments(), - static fn ( $comment ): bool => $comment instanceof DocComment - ); -} - /** * @template T * @param iterable $infos @@ -5178,8 +5220,9 @@ static function (FuncInfo $funcInfo) use ($fileInfo, &$generatedFunctionDeclarat $php80MinimumCompatibility = $fileInfo->getMinimumPhpVersionIdCompatibility() === null || $fileInfo->getMinimumPhpVersionIdCompatibility() >= PHP_80_VERSION_ID; if ($fileInfo->generateClassEntries) { - $attributeInitializationCode = generateFunctionAttributeInitialization($fileInfo->funcInfos, $allConstInfos, $fileInfo->getMinimumPhpVersionIdCompatibility(), null); - $attributeInitializationCode .= generateGlobalConstantAttributeInitialization($fileInfo->constInfos, $allConstInfos, $fileInfo->getMinimumPhpVersionIdCompatibility(), null); + $declaredStrings = []; + $attributeInitializationCode = generateFunctionAttributeInitialization($fileInfo->funcInfos, $allConstInfos, $fileInfo->getMinimumPhpVersionIdCompatibility(), null, $declaredStrings); + $attributeInitializationCode .= generateGlobalConstantAttributeInitialization($fileInfo->constInfos, $allConstInfos, $fileInfo->getMinimumPhpVersionIdCompatibility(), null, $declaredStrings); if ($attributeInitializationCode) { if (!$php80MinimumCompatibility) { $attributeInitializationCode = "\n#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")" . $attributeInitializationCode . "#endif\n"; @@ -5204,18 +5247,7 @@ static function (FuncInfo $funcInfo) use ($fileInfo, &$generatedFunctionDeclarat $code .= "}\n"; } - $code .= generateClassEntryCode($fileInfo, $allConstInfos); - } - - return $code; -} - -/** @param array $allConstInfos */ -function generateClassEntryCode(FileInfo $fileInfo, array $allConstInfos): string { - $code = ""; - - foreach ($fileInfo->classInfos as $class) { - $code .= "\n" . $class->getRegistration($allConstInfos); + $code .= $fileInfo->generateClassEntryCode($allConstInfos); } return $code; @@ -5228,19 +5260,13 @@ function generateFunctionEntries(?Name $className, array $funcInfos, ?string $co return ''; } - $code = "\n"; - - if ($cond) { - $code .= "#if {$cond}\n"; - } - $functionEntryName = "ext_functions"; if ($className) { $underscoreName = implode("_", $className->getParts()); $functionEntryName = "class_{$underscoreName}_methods"; } - $code .= "static const zend_function_entry {$functionEntryName}[] = {\n"; + $code = "\nstatic const zend_function_entry {$functionEntryName}[] = {\n"; $code .= generateCodeWithConditions($funcInfos, "", static function (FuncInfo $funcInfo) { return $funcInfo->getFunctionEntry(); }, $cond); @@ -5248,18 +5274,22 @@ function generateFunctionEntries(?Name $className, array $funcInfos, ?string $co $code .= "};\n"; if ($cond) { - $code .= "#endif\n"; + $code = "\n#if {$cond}{$code}#endif\n"; } return $code; } -/** @param iterable $funcInfos */ -function generateFunctionAttributeInitialization(iterable $funcInfos, array $allConstInfos, ?int $phpVersionIdMinimumCompatibility, ?string $parentCond = null): string { +/** + * @param iterable $funcInfos + * @param array &$declaredStrings Map of string content to + * the name of a zend_string already created with that content + */ +function generateFunctionAttributeInitialization(iterable $funcInfos, array $allConstInfos, ?int $phpVersionIdMinimumCompatibility, ?string $parentCond = null, array &$declaredStrings = []): string { return generateCodeWithConditions( $funcInfos, "", - static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCompatibility) { + static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCompatibility, &$declaredStrings) { $code = null; if ($funcInfo->name instanceof MethodName) { @@ -5268,12 +5298,22 @@ static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCo $functionTable = "CG(function_table)"; } + // Make sure we don't try and use strings that might only be + // conditionally available; string reuse is only among declarations + // that are always there + if ($funcInfo->cond) { + $useDeclared = []; + } else { + $useDeclared = &$declaredStrings; + } + foreach ($funcInfo->attributes as $key => $attribute) { $code .= $attribute->generateCode( "zend_add_function_attribute(zend_hash_str_find_ptr($functionTable, \"" . $funcInfo->name->getNameForAttributes() . "\", sizeof(\"" . $funcInfo->name->getNameForAttributes() . "\") - 1)", "func_" . $funcInfo->name->getNameForAttributes() . "_$key", $allConstInfos, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $useDeclared ); } @@ -5283,7 +5323,8 @@ static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCo "zend_add_parameter_attribute(zend_hash_str_find_ptr($functionTable, \"" . $funcInfo->name->getNameForAttributes() . "\", sizeof(\"" . $funcInfo->name->getNameForAttributes() . "\") - 1), $index", "func_{$funcInfo->name->getNameForAttributes()}_arg{$index}_$key", $allConstInfos, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $useDeclared ); } } @@ -5297,37 +5338,53 @@ static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCo /** * @param iterable $constInfos * @param array $allConstInfos + * @param array &$declaredStrings Map of string content to + * the name of a zend_string already created with that content */ function generateGlobalConstantAttributeInitialization( iterable $constInfos, array $allConstInfos, ?int $phpVersionIdMinimumCompatibility, - ?string $parentCond = null + ?string $parentCond = null, + array &$declaredStrings = [] ): string { $isConditional = false; if ($phpVersionIdMinimumCompatibility !== null && $phpVersionIdMinimumCompatibility < PHP_85_VERSION_ID) { $isConditional = true; - $phpVersionIdMinimumCompatibility = PHP_85_VERSION_ID; } $code = generateCodeWithConditions( $constInfos, "", - static function (ConstInfo $constInfo) use ($allConstInfos, $phpVersionIdMinimumCompatibility) { + static function (ConstInfo $constInfo) use ($allConstInfos, $isConditional, &$declaredStrings) { $code = ""; if ($constInfo->attributes === []) { return null; } + // Make sure we don't try and use strings that might only be + // conditionally available; string reuse is only among declarations + // that are always there + if ($constInfo->cond) { + $useDeclared = []; + } else { + $useDeclared = &$declaredStrings; + } $constName = str_replace('\\', '\\\\', $constInfo->name->__toString()); $constVarName = 'const_' . $constName; - $code .= "\tzend_constant *$constVarName = zend_hash_str_find_ptr(EG(zend_constants), \"" . $constName . "\", sizeof(\"" . $constName . "\") - 1);\n"; + // The entire attribute block will be conditional if PHP < 8.5 is + // supported, but also if PHP < 8.5 is supported we need to search + // for the constant; see GH-19029 + if ($isConditional) { + $code .= "\tzend_constant *$constVarName = zend_hash_str_find_ptr(EG(zend_constants), \"" . $constName . "\", sizeof(\"" . $constName . "\") - 1);\n"; + } foreach ($constInfo->attributes as $key => $attribute) { $code .= $attribute->generateCode( "zend_add_global_constant_attribute($constVarName", $constVarName . "_$key", $allConstInfos, - $phpVersionIdMinimumCompatibility + PHP_85_VERSION_ID, + $useDeclared ); } @@ -5344,25 +5401,37 @@ static function (ConstInfo $constInfo) use ($allConstInfos, $phpVersionIdMinimum /** * @param iterable $constInfos * @param array $allConstInfos + * @param array &$declaredStrings Map of string content to + * the name of a zend_string already created with that content */ function generateConstantAttributeInitialization( iterable $constInfos, array $allConstInfos, ?int $phpVersionIdMinimumCompatibility, - ?string $parentCond = null + ?string $parentCond = null, + array &$declaredStrings = [] ): string { return generateCodeWithConditions( $constInfos, "", - static function (ConstInfo $constInfo) use ($allConstInfos, $phpVersionIdMinimumCompatibility) { + static function (ConstInfo $constInfo) use ($allConstInfos, $phpVersionIdMinimumCompatibility, &$declaredStrings) { $code = null; + // Make sure we don't try and use strings that might only be + // conditionally available; string reuse is only among declarations + // that are always there + if ($constInfo->cond) { + $useDeclared = []; + } else { + $useDeclared = &$declaredStrings; + } foreach ($constInfo->attributes as $key => $attribute) { $code .= $attribute->generateCode( "zend_add_class_constant_attribute(class_entry, const_" . $constInfo->name->getDeclarationName(), "const_" . $constInfo->name->getDeclarationName() . "_$key", $allConstInfos, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $useDeclared ); } @@ -5375,11 +5444,14 @@ static function (ConstInfo $constInfo) use ($allConstInfos, $phpVersionIdMinimum /** * @param iterable $propertyInfos * @param array $allConstInfos + * @param array &$declaredStrings Map of string content to + * the name of a zend_string already created with that content */ function generatePropertyAttributeInitialization( iterable $propertyInfos, array $allConstInfos, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array &$declaredStrings ): string { $code = ""; foreach ($propertyInfos as $propertyInfo) { @@ -5388,7 +5460,8 @@ function generatePropertyAttributeInitialization( "zend_add_property_attribute(class_entry, property_" . $propertyInfo->name->getDeclarationName(), "property_" . $propertyInfo->name->getDeclarationName() . "_" . $key, $allConstInfos, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $declaredStrings ); } } @@ -5411,80 +5484,6 @@ function generateOptimizerInfo(array $funcMap): string { return $code; } -/** - * @param array $flagsByPhpVersions - * @return string - */ -function generateVersionDependentFlagCode(string $codeTemplate, array $flagsByPhpVersions, ?int $phpVersionIdMinimumCompatibility): string -{ - $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); - - // 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 - $code = ''; - $i = 0; - foreach (array_reverse($flagsByPhpVersions, true) as $version => $versionFlags) { - $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; - - $i++; - } - - return $code; -} - /** * @param array $constMap * @param array $undocumentedConstMap @@ -6082,7 +6081,7 @@ function initPhpParser() { } $isInitialized = true; - $version = "5.5.0"; + $version = "5.6.1"; $phpParserDir = __DIR__ . "/PHP-Parser-$version"; if (!is_dir($phpParserDir)) { installPhpParser($version, $phpParserDir); @@ -6376,7 +6375,7 @@ function(?ArgInfo $aliasArg, ?ArgInfo $aliasedArg) use ($aliasFunc, $aliasedFunc if ($verifyManual) { foreach ($undocumentedConstMap as $constName => $info) { - if ($info->name->isClassConst() || $info->isUndocumentable) { + if ($info->name instanceof ClassConstName || $info->isUndocumentable) { continue; } diff --git a/build/php.m4 b/build/php.m4 index 8cdf318083fbb..e82e856667e94 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -54,7 +54,11 @@ AC_DEFUN([PHP_EXPAND_PATH],[ changequote({,}) ep_dir=$(echo $1|$SED 's%/*[^/][^/]*/*$%%') changequote([,]) - ep_realdir=$(cd "$ep_dir" && pwd) + if test -z $ep_dir ; then + ep_realdir=$(pwd) + else + ep_realdir=$(cd "$ep_dir" && pwd) + fi $2="$ep_realdir"/$(basename "$1") fi ]) @@ -1014,7 +1018,9 @@ dnl _PHP_CHECK_SIZEOF(type, cross-value, extra-headers [, found-action [, not-fo dnl dnl Internal helper macro. dnl -AC_DEFUN([_PHP_CHECK_SIZEOF], [ +AC_DEFUN([_PHP_CHECK_SIZEOF], +[m4_warn([obsolete], + [The PHP_CHECK_SIZEOF macro is obsolete. Use AC_CHECK_SIZEOF.]) php_cache_value=php_cv_sizeof_[]$1 AC_CACHE_VAL(php_cv_sizeof_[]$1, [ old_LIBS=$LIBS @@ -1056,6 +1062,9 @@ ifelse([$5],[],,[else $5]) dnl dnl PHP_CHECK_SIZEOF(type, cross-value, extra-headers) dnl +dnl Checks the size of specified "type". This macro is obsolete as of PHP 8.5 in +dnl favor of the AC_CHECK_SIZEOF. +dnl AC_DEFUN([PHP_CHECK_SIZEOF], [ AC_MSG_CHECKING([size of $1]) _PHP_CHECK_SIZEOF($1, $2, $3, [ @@ -1791,7 +1800,17 @@ AC_DEFUN([PHP_SETUP_ICONV], [ dnl Check external libs for iconv funcs. AS_VAR_IF([found_iconv], [no], [ - for i in $PHP_ICONV /usr/local /usr; do + + dnl Find /opt/homebrew/opt/libiconv on macOS + dnl See: https://github.com/php/php-src/pull/19475 + php_brew_prefix=no + AC_CHECK_PROG([BREW], [brew], [brew]) + if test -n "$BREW"; then + AC_MSG_CHECKING([for homebrew prefix]) + php_brew_prefix=$($BREW --prefix 2> /dev/null) + fi + + for i in $PHP_ICONV $php_brew_prefix/opt/libiconv /usr/local /usr; do if test -r $i/include/gnu-libiconv/iconv.h; then ICONV_DIR=$i ICONV_INCLUDE_DIR=$i/include/gnu-libiconv diff --git a/configure.ac b/configure.ac index e4bd8162a2ebc..5059f55127b06 100644 --- a/configure.ac +++ b/configure.ac @@ -128,6 +128,17 @@ AS_VAR_IF([cross_compiling], [yes], AC_MSG_RESULT([$BUILD_CC])], [BUILD_CC=$CC]) +dnl The macro AC_PROG_CC_C99 sets the shell variable ac_cv_prog_cc_c99 to 'no' +dnl if the compiler does not support C99.i.e. does not support any of _Bool, +dnl flexible arrays, inline, long long int, mixed code and declarations, +dnl named initialization of structs, restrict, varargs macros, variable +dnl declarations in for loops and variable length arrays. +dnl +dnl https://www.gnu.org/software/autoconf/manual/autoconf-2.60/html_node/C-Compiler.html +if test "$ac_cv_prog_cc_c99" = no; then + AC_MSG_ERROR([C compiler would not accept C99 code]) +fi + dnl Support systems with system libraries in e.g. /usr/lib64. PHP_ARG_WITH([libdir], [for system library directory], @@ -206,7 +217,12 @@ dnl supports it. This can help reduce the binary size and startup time. AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], [CFLAGS="$CFLAGS -fvisibility=hidden"]) +dnl to disable executable stack on haiku due +dnl to missing elf .note.GNU-stack part case $host_alias in + *haiku*) + LDFLAGS="$LDFLAGS -Wl,-z,noexecstack" + ;; *solaris*) CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS" ;; @@ -451,11 +467,6 @@ AC_CHECK_TYPES([socklen_t], [], [], [ #endif ]) -dnl These are defined elsewhere than stdio.h. -PHP_CHECK_SIZEOF([intmax_t], [0]) -PHP_CHECK_SIZEOF([ssize_t], [8]) -PHP_CHECK_SIZEOF([ptrdiff_t], [8]) - dnl Check stdint types (must be after header check). PHP_CHECK_STDINT_TYPES @@ -545,7 +556,6 @@ AC_CHECK_FUNCS(m4_normalize([ getgrnam_r gethostname getloadavg - getlogin getprotobyname getprotobynumber getpwnam_r @@ -565,6 +575,7 @@ AC_CHECK_FUNCS(m4_normalize([ memmem mempcpy memrchr + memset_explicit mkstemp mmap nice @@ -582,7 +593,6 @@ AC_CHECK_FUNCS(m4_normalize([ statvfs std_syslog strcasecmp - strnlen strptime strtok_r symlink diff --git a/docs/release-process.md b/docs/release-process.md index 6eec8ff9f6435..08b95df53513f 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -96,6 +96,13 @@ releases. `user.signingKey` values to use with your local PHP repositories. See [Conditional Includes For Git Config][] for more information. +11. Any time you see a placeholder like `php-X.Y.ZRCn`, the `RCn` is not always + a release candidate number. The placeholder could also represent any of: + * php-8.4.0alpha1 (initial alpha version) + * php-8.4.0beta2 (one of the beta versions) + * php-8.4.0 (initial GA) + * php-8.4.9 (periodic bugfix or security release) + ## Packaging a non-stable release (alpha/beta/RC) @@ -162,7 +169,10 @@ slightly different steps. We'll call attention where the steps differ. 4. Using your local-only release branch, bump the version numbers in `main/php_version.h`, `Zend/zend.h`, `configure.ac`, and possibly `NEWS`. - + + The date for NEWS should be the date of the announcement (Thursday), + *not* the date of the tagging (Tuesday). + For examples, see [Update versions for PHP 8.1.0beta3][] (for a pre-GA example) or [Update versions for PHP 8.1.6RC1][] along with [Update NEWS for PHP 8.1.6RC1][] (for a post-GA example). @@ -200,8 +210,8 @@ slightly different steps. We'll call attention where the steps differ. > Do *not* bump the API versions after RC1. 5. Compile and run `make test`, with and without ZTS (Zend Thread Safety), using - the correct Bison and re2c versions, e.g., for PHP 7.4, Bison 3.0.0 and re2c - 0.13.4 are required, as a minimum. + the correct Bison and re2c versions, e.g., for PHP 8.5, Bison 3.0.0 and re2c + 1.0.3 are required, as a minimum. For example: @@ -209,7 +219,7 @@ slightly different steps. We'll call attention where the steps differ. # With ZTS make distclean || \ ./buildconf --force \ - && ./configure --enable-zts --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ + && ./configure --enable-zts --disable-all --enable-debug --enable-opcache-jit \ && make -j$(nproc) \ && make test TEST_PHP_ARGS="-q -j$(nproc)" \ || ./sapi/cli/php -v @@ -217,7 +227,7 @@ slightly different steps. We'll call attention where the steps differ. # Without ZTS make distclean || \ ./buildconf --force \ - && ./configure --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ + && ./configure --disable-all --enable-debug --enable-opcache-jit \ && make -j$(nproc) \ && make test TEST_PHP_ARGS="-q -j$(nproc)" \ || ./sapi/cli/php -v @@ -247,9 +257,12 @@ slightly different steps. We'll call attention where the steps differ. ```shell git add -p - git commit --gpg-sign=YOURKEYID -m "[ci skip] Update NEWS for PHP X.Y.Z alpha2" + git commit --gpg-sign=YOURKEYID -m "[ci skip] Update NEWS for PHP X.Y.0 alpha2" ``` + The NEWS is updated at the *start* of the cycle for the next tag, e.g. + [Update NEWS for PHP 8.2.0 alpha2][] was sent as part of tagging 8.2.0 alpha **1**. + 🔷 **For post-GA releases only,** switch back to the *version branch* for your release (e.g., `PHP-8.2`) and bump the version numbers in `main/php_version.h`, `Zend/zend.h`, `configure.ac` and `NEWS`. This prepares @@ -283,7 +296,8 @@ slightly different steps. We'll call attention where the steps differ. ```shell git push upstream php-X.Y.ZRCn # tag name git push upstream PHP-X.Y.Z # patch-level version branch (post-GA only) - git push upstream PHP-X.Y # version branch + git push upstream PHP-X.Y # version branch (post-branch creation only) + git push upstream master # version branch (pre-branch creation only) ``` > 🚨 **Attention** \ @@ -365,6 +379,10 @@ slightly different steps. We'll call attention where the steps differ. Follow the documentation in the file for editing the QA release information. + > 🚨 **Attention** \ + > **For pre-GA releases only,** don't commit yet, because you need to add an + > announcement with the release. After updating `$QA_RELEASES`, skip to step 2 below. + Add, commit, and push your changes, when finished. ```shell @@ -408,6 +426,15 @@ slightly different steps. We'll call attention where the steps differ. text slightly to indicate progression through the pre-release cycle. For example, here are all the news posts for the pre-GA releases of PHP 8.1.0: + > 💬 **Hint** \ + > If you are going to base your language on one of these old announcements, + > remember that + > * `qa.php.net` has been replaced with https://www.php.net/release-candidates.php + > * `bugs.php.net` has been replaced with GitHub issues, use + > `https://github.com/php/php-src/issues/new?template=bug_report.yml` + > to link directly to the form for creating a new bug report. + > * Since 8.4 there have only been 4 release candidates for PHP X.Y.0, rather than 6. + * [Announce 8.1.0alpha1](https://github.com/php/web-php/commit/57b9675c8d8550493289fa1fba77427c93cdd472) * [Announce 8.1.0alpha2](https://github.com/php/web-php/commit/cec044fc0763f5cfa77d0e79479f8b6279023570) * [Announce 8.1.0alpha3](https://github.com/php/web-php/commit/5c480765f444a3fddfd575e01fe0be3fcfdde05b) @@ -431,7 +458,7 @@ slightly different steps. We'll call attention where the steps differ. > When a version is in its post-GA phase, we do not post news entries for > non-stable releases. -3. Wait for the web and qa sites to update with the new information before +3. Wait for the php site to update with the new information before sending announcements. This could take up to an hour. 4. Send *separate* announcement emails to: @@ -447,6 +474,15 @@ slightly different steps. We'll call attention where the steps differ. Here are a few examples of non-stable release announcement emails: + > 💬 **Hint** \ + > If you are going to base your language on one of these old announcements, + > remember that + > * `qa.php.net` has been replaced with https://www.php.net/release-candidates.php + > * `bugs.php.net` has been replaced with GitHub issues, use + > `https://github.com/php/php-src/issues/new?template=bug_report.yml` + > to link directly to the form for creating a new bug report. + > * Since 8.4 there have only been 4 release candidates for PHP X.Y.0, rather than 6. + * [PHP 8.1.0alpha1 is available for testing](https://news-web.php.net/php.qa/69043) * [PHP 8.1.0beta3 available for testing](https://news-web.php.net/php.qa/69079) * [PHP 8.1.0RC6 available for testing](https://news-web.php.net/php.qa/69117) @@ -464,9 +500,16 @@ slightly different steps. We'll call attention where the steps differ. > report any potential bugs that should be fixed before the upcoming GA > release. -5. 🔶 **For pre-GA *RCs* only,** coordinate with the social media team (i.e., - Derick) to post a tweet with the RC release announcement and link to the news - entry on php.net. ([@official_php](https://twitter.com/official_php)) +5. 🔶 **For alphas, betas, and *pre-GA* RCs,** coordinate with the + social media team (i.e., Derick and Sergey) to post a toot containing the + release announcement and link to the news entry on php.net. + You can send a PR to [toot-together](https://github.com/derickr/toot-together/) + with highlights from the NEWS file yourself, if you want. + + * [Annonce 8.5.0alpha1](https://github.com/derickr/toot-together/pull/42) + * [Annonce 8.5.0alpha2](https://github.com/derickr/toot-together/pull/47) + + We post to [@php@fosstodon.org](https://fosstodon.org/@php). ## Packaging a stable release @@ -519,8 +562,8 @@ slightly different steps. We'll call attention where the steps differ. an example. 6. Compile and run `make test`, with and without ZTS (Zend Thread Safety), using - the correct Bison and re2c versions, e.g., for PHP 7.4, Bison 3.0.0 and re2c - 0.13.4 are required, as a minimum. + the correct Bison and re2c versions, e.g., for PHP 8.5, Bison 3.0.0 and re2c + 1.0.3 are required, as a minimum. For example: @@ -528,7 +571,7 @@ slightly different steps. We'll call attention where the steps differ. # With ZTS make distclean || \ ./buildconf --force \ - && ./configure --enable-zts --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ + && ./configure --enable-zts --disable-all --enable-debug --enable-opcache-jit \ && make -j$(nproc) \ && make test TEST_PHP_ARGS="-q -j$(nproc)" \ || ./sapi/cli/php -v @@ -536,7 +579,7 @@ slightly different steps. We'll call attention where the steps differ. # Without ZTS make distclean || \ ./buildconf --force \ - && ./configure --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ + && ./configure --disable-all --enable-debug --enable-opcache-jit \ && make -j$(nproc) \ && make test TEST_PHP_ARGS="-q -j$(nproc)" \ || ./sapi/cli/php -v @@ -720,10 +763,10 @@ slightly different steps. We'll call attention where the steps differ. The array probably contains information about the RC released two weeks ago in preparation for the current release. Since the current release is now GA, - it's time to remove the RC build from the QA website. + it's time to remove the RC build from the release candidates page. It is sufficient to set the `number` property for the release to `0` to - stop displaying the RC build on the QA website. You may also remove the + stop displaying the RC build on the release candidates page. You may also remove the sha256 hashes for the RC tarballs, but it's not necessary. 9. Review all the changes in `web-php`, commit, and push them. @@ -835,25 +878,37 @@ If you choose to create a patch-level release, follow these steps: mailinglist. -## Feature freeze +## Soft feature freeze -A major/minor version [feature freeze][] occurs with the first beta release. -Specifically, it occurs when the first beta release is packaged, which means the -feature freeze occurs two days before the first beta release. +A major/minor version soft feature freeze occurs with the first beta release. +This is a soft feature freeze because features can still be merged with RM +approval. -The feature freeze for `php-src` means that we will not accept any new features -after the date of the feature freeze. For any RFCs to be included in the new -version, they should be discussed and have the voting polls closed no later than -the feature freeze date. However, this does not mean the new feature must have a -complete implementation by this date. - -Following the feature freeze, the focus of work for the new version will be on -fixing bugs, writing tests, and completing/polishing all accepted features. +For any RFCs to be included in the new release, they should be discussed and +have their voting polls closed no later than when the first beta is released. +However, this does not mean the new feature must have a complete implementation +by this date. Such implementation can be merged only with RM approval and must +be done before the hard feature freeze. As a courtesy to the community, the release managers should remind others about -the upcoming feature freeze by posting reminders to internals@lists.php.net at -4-weeks, 3-weeks, 2-weeks, and 1-week prior to the feature freeze. This is a -recommendation and the intervals may vary based on work load. +the upcoming soft feature freeze by posting reminders to +internals@lists.php.net at 5 weeks, 4 weeks, 3 weeks, 2 weeks, and 1 week prior +to this feature freeze. This is a recommendation and the intervals may vary +based on workload. The reminder should also contain a note with dates for +the last allowed RFC to start voting. + +## Hard feature freeze + +A major/minor version hard [feature freeze][] occurs with the first RC release. +Specifically, it occurs when the first RC release is packaged, which means the +hard feature freeze occurs two days before the first RC release. + +The hard feature freeze for php-src means that we will not accept any new +features after the date of the hard feature freeze. + +Following the hard feature freeze, the focus of work for the new version will +be on fixing bugs, writing tests, and preparing documentation for all accepted +features. ## Forking a new version branch @@ -981,8 +1036,13 @@ volunteers to begin the selection process for the next release managers. 2. Request membership to the [release managers group](https://github.com/orgs/php/teams/release-managers) on GitHub. -3. Subscribe to the php-announce@lists.php.net mailing list by emailing - php-announce+subscribe@lists.php.net +3. Make sure you are subscribed to all of the mailing lists that you will need to send + announcements to, since you cannot post to the lists otherwise: + + * internals@lists.php.net (email internals+subscribe@lists.php.net) + * php-announce@lists.php.net (email php-announce+subscribe@lists.php.net) + * php-general@lists.php.net (email php-general+subscribe@lists.php.net) + * php-qa@lists.php.net (email php-qa+subscribe@lists.php.net) 4. Email systems@php.net to get setup for access to downloads.php.net, to be added to the release-managers@php.net distribution list, and to be added to diff --git a/docs/source/miscellaneous/running-tests.rst b/docs/source/miscellaneous/running-tests.rst index c85e9f4c24dea..bb2c56dcecd25 100644 --- a/docs/source/miscellaneous/running-tests.rst +++ b/docs/source/miscellaneous/running-tests.rst @@ -11,16 +11,16 @@ work). Therefore you can execute the script as follows: .. code:: shell - TEST_PHP_EXECUTABLE=sapi/cli/php \ sapi/cli/php [-c /path/to/php.ini] run-tests.php [ext/foo/tests/GLOB] ****************************************** Which php executable does make test use? ****************************************** -If you are running the ``run-tests.php`` script from the command line (as above) you must set the +If you are running the ``run-tests.php`` script from the command line (as above) you can set the ``TEST_PHP_EXECUTABLE`` environment variable to explicitly select the PHP executable that is to be -tested, that is, used to run the test scripts. +tested, that is, used to run the test scripts, otherwise it will use the PHP CLI binary that you +have compiled (``sapi/cli/php``). If you run the tests using make test, the PHP CLI and CGI executables are automatically set for you. ``make test`` executes ``run-tests.php`` script with the CLI binary. Some test scripts such as @@ -58,6 +58,31 @@ Tester can easily execute tests selectively with as follows: ./sapi/cli/php run-tests.php ext/mbstring/* ./sapi/cli/php run-tests.php ext/mbstring/020.phpt +********************* + Test Runner Options +********************* + +The ``run-tests.php`` test runner has many options. You can see these options by using the ``-h`` +option with ``run-tests.php``. + +You can set options by specifying them on the command line when you run ``php run-tests.php`` or if +you use ``make test`` through the ``TEST_PHP_ARGS`` environment variable: + +.. code:: shell + + php run-tests.php -j24 + # or + TEST_PHP_ARGS="-j24" make test + +Running Tests in Parallel +========================= + +The test runner can run tests in parallel, by using the ``-j`` option: + +.. code:: shell + + php run-tests.php -j24 ext/date/*.phpt + ************** Test results ************** diff --git a/docs/source/miscellaneous/stubs.rst b/docs/source/miscellaneous/stubs.rst index 3899fe3084196..616d306895542 100644 --- a/docs/source/miscellaneous/stubs.rst +++ b/docs/source/miscellaneous/stubs.rst @@ -223,7 +223,8 @@ The generated ``class_Atmosphere_methods`` must be used when registering the ``A Additional meta information can be attached to functions, with the following PHPDoc tags: -- ``@deprecated``: Triggers the usual deprecation notice when the function/method is called. +- ``@deprecated``: Triggers the usual deprecation notice when the function/method is called. As of + PHP 8.4 the `#[Deprecated]` attribute should be used instead. - ``@alias``: If a function/method is an alias of another function/method, then the aliased function/method name has to be provided as value. E.g. the function ``sizeof()`` has the ``@alias @@ -244,7 +245,7 @@ Additional meta information can be attached to functions, with the following PHP - ``@genstubs-expose-comment-block``: By adding this annotation at the beginning of a PHPDoc block, the content of the PHPDoc block will be exposed for - `ReflectionFunctionAbstract::getDocComment()`. This feature was added in PHP 8.4.0. + `ReflectionFunctionAbstract::getDocComment()`. This feature was added in PHP 8.4. .. _tentative return type: https://wiki.php.net/rfc/internal_method_return_types @@ -337,7 +338,7 @@ Like functions and methods, classes also support meta information passed via PHP - ``@genstubs-expose-comment-block``: By adding this tag at the beginning of a PHPDoc block, the content of the PHPDoc block will be exposed for `ReflectionClass::getDocComment()`. This feature - is only available as of PHP 8.4.0. + is only available as of PHP 8.4. This is an example with all the flags: @@ -452,11 +453,12 @@ with ``@cvalue M_PI`` to the C-level constant ``M_PI`` (define by PHP's internal Constants can take the following extra meta information passed via PHPDoc tags: -- ``@deprecated``: Triggers a deprecation notice when the constant is used. +- ``@deprecated``: Triggers a deprecation notice when the constant is used. As of PHP 8.5 the + `#[Deprecated]` attribute should be used instead. - ``@genstubs-expose-comment-block``: By adding this tag at the beginning of a PHPDoc block, the content of the PHPDoc block will be exposed for `ReflectionClass::getDocComment()`. This feature - is only available as of PHP 8.4.0. + is only available as of PHP 8.4. ************************************ Maintaining Backward Compatibility diff --git a/ext/calendar/calendar.c b/ext/calendar/calendar.c index 4cb6a2fa9a08a..5e948fa1567a7 100644 --- a/ext/calendar/calendar.c +++ b/ext/calendar/calendar.c @@ -197,6 +197,16 @@ PHP_FUNCTION(cal_days_in_month) RETURN_THROWS(); } + if (UNEXPECTED(month <= 0 || month > INT32_MAX - 1)) { + zend_argument_value_error(2, "must be between 1 and %d", INT32_MAX - 1); + RETURN_THROWS(); + } + + if (UNEXPECTED(year > INT32_MAX - 1)) { + zend_argument_value_error(3, "must be less than %d", INT32_MAX - 1); + RETURN_THROWS(); + } + calendar = &cal_conversion_table[cal]; sdn_start = calendar->to_jd(year, month, 1); @@ -242,6 +252,21 @@ PHP_FUNCTION(cal_to_jd) RETURN_THROWS(); } + if (UNEXPECTED(month <= 0 || month > INT32_MAX - 1)) { + zend_argument_value_error(2, "must be between 1 and %d", INT32_MAX - 1); + RETURN_THROWS(); + } + + if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(day))) { + zend_argument_value_error(3, "must be between %d and %d", INT32_MIN, INT32_MAX); + RETURN_THROWS(); + } + + if (UNEXPECTED(year > INT32_MAX - 1)) { + zend_argument_value_error(4, "must be less than %d", INT32_MAX - 1); + RETURN_THROWS(); + } + RETURN_LONG(cal_conversion_table[cal].to_jd(year, month, day)); } /* }}} */ diff --git a/ext/calendar/tests/cal_days_in_month_error1.phpt b/ext/calendar/tests/cal_days_in_month_error1.phpt index f334888479f20..e110c13cc2a78 100644 --- a/ext/calendar/tests/cal_days_in_month_error1.phpt +++ b/ext/calendar/tests/cal_days_in_month_error1.phpt @@ -12,7 +12,7 @@ try { echo "{$ex->getMessage()}\n"; } try{ - cal_days_in_month(CAL_GREGORIAN,0, 2009); + cal_days_in_month(CAL_GREGORIAN,20, 2009); } catch (ValueError $ex) { echo "{$ex->getMessage()}\n"; } diff --git a/ext/calendar/tests/gh19371.phpt b/ext/calendar/tests/gh19371.phpt new file mode 100644 index 0000000000000..1d807a9838867 --- /dev/null +++ b/ext/calendar/tests/gh19371.phpt @@ -0,0 +1,61 @@ +--TEST-- +GH-19371 (integer overflow in calendar.c) +--SKIPIF-- + +--EXTENSIONS-- +calendar +--FILE-- +getMessage(), "\n"; +} +try { + echo cal_days_in_month(CAL_GREGORIAN, PHP_INT_MIN, 1); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + echo cal_days_in_month(CAL_GREGORIAN, PHP_INT_MAX, 1); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +try { + echo cal_to_jd(CAL_GREGORIAN, PHP_INT_MIN, 1, 1); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + echo cal_to_jd(CAL_GREGORIAN, PHP_INT_MAX, 1, 1); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + echo cal_to_jd(CAL_GREGORIAN, 1, PHP_INT_MIN, 1); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + echo cal_to_jd(CAL_GREGORIAN, 1, PHP_INT_MAX, 1); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + echo cal_to_jd(CAL_GREGORIAN, 1, 1, PHP_INT_MAX); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +cal_days_in_month(): Argument #3 ($year) must be less than 2147483646 +cal_days_in_month(): Argument #2 ($month) must be between 1 and 2147483646 +cal_days_in_month(): Argument #2 ($month) must be between 1 and 2147483646 +cal_to_jd(): Argument #2 ($month) must be between 1 and 2147483646 +cal_to_jd(): Argument #2 ($month) must be between 1 and 2147483646 +cal_to_jd(): Argument #3 ($day) must be between -2147483648 and 2147483647 +cal_to_jd(): Argument #3 ($day) must be between -2147483648 and 2147483647 +cal_to_jd(): Argument #4 ($year) must be less than 2147483646 diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index af980b7b86f2a..638fc5d8a3ae6 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -514,6 +514,7 @@ zend_object_handlers php_com_object_handlers = { php_com_object_free_storage, zend_objects_destroy_object, php_com_object_clone, + NULL, /* clone_with */ com_property_read, com_property_write, com_read_dimension, diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c index ea0e9e47a13d9..ec79faa30a32b 100644 --- a/ext/com_dotnet/com_saproxy.c +++ b/ext/com_dotnet/com_saproxy.c @@ -402,6 +402,7 @@ zend_object_handlers php_com_saproxy_handlers = { saproxy_free_storage, zend_objects_destroy_object, saproxy_clone, + NULL, /* clone_with */ saproxy_property_read, saproxy_property_write, saproxy_read_dimension, diff --git a/ext/com_dotnet/com_variant.c b/ext/com_dotnet/com_variant.c index 23cbd078fb472..7e63d66b3d3a1 100644 --- a/ext/com_dotnet/com_variant.c +++ b/ext/com_dotnet/com_variant.c @@ -32,7 +32,7 @@ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage) SAFEARRAY *sa = NULL; SAFEARRAYBOUND bound; HashPosition pos; - int keytype; + zend_hash_key_type keytype; zend_string *strindex; zend_ulong intindex = 0; VARIANT *va; diff --git a/ext/com_dotnet/com_wrapper.c b/ext/com_dotnet/com_wrapper.c index 6e885fa802e9f..3d05e17affae7 100644 --- a/ext/com_dotnet/com_wrapper.c +++ b/ext/com_dotnet/com_wrapper.c @@ -423,7 +423,7 @@ static void generate_dispids(php_dispatchex *disp) HashPosition pos; zend_string *name = NULL; zval *tmp, tmp2; - int keytype; + zend_hash_key_type keytype; zend_long pid; if (disp->dispid_to_name == NULL) { diff --git a/ext/ctype/tests/lc_ctype_inheritance.phpt b/ext/ctype/tests/lc_ctype_inheritance.phpt index 6f37941d8f481..98a0c35cf00e6 100644 --- a/ext/ctype/tests/lc_ctype_inheritance.phpt +++ b/ext/ctype/tests/lc_ctype_inheritance.phpt @@ -4,6 +4,7 @@ Do not inherit LC_CTYPE from environment ctype --SKIPIF-- diff --git a/ext/curl/config.m4 b/ext/curl/config.m4 index f3c39b4c5179d..bbb41fdde3223 100644 --- a/ext/curl/config.m4 +++ b/ext/curl/config.m4 @@ -15,8 +15,8 @@ if test "$PHP_CURL" != "no"; then AC_MSG_RESULT([$CURL_SSL]) AS_IF([test "x$PHP_THREAD_SAFETY" = xyes && test "x$CURL_SSL" = xyes], - [AC_CACHE_CHECK([whether libcurl is linked against old OpenSSL < 1.1], - [php_cv_lib_curl_ssl], [ + [AC_CACHE_CHECK([whether libcurl is linked against a supported OpenSSL version], + [php_cv_lib_curl_ssl_supported], [ save_LIBS=$LIBS save_CFLAGS=$CFLAGS LIBS="$LIBS $CURL_SHARED_LIBADD" @@ -34,17 +34,14 @@ if test "$PHP_CURL" != "no"; then while(*ptr == ' ') ++ptr; int major, minor; - if (sscanf(ptr, "OpenSSL/%d", &major) == 1) { - if (major >= 3) { - /* OpenSSL version 3 or later */ - return 4; - } - } if (sscanf(ptr, "OpenSSL/%d.%d", &major, &minor) == 2) { - if (major > 1 || (major == 1 && minor >= 1)) { - /* OpenSSL version 1.1 or later */ + /* Check for 1.1.1+ (including 1.1.1a, 1.1.1b, etc.) */ + if ((major > 1) || (major == 1 && minor == 1 && strncmp(ptr + 12, "1", 1) == 0)) { + /* OpenSSL 1.1.1+ - supported */ return 3; } + /* OpenSSL 1.1.0 and earlier - unsupported */ + return 0; } if (strncasecmp(ptr, "OpenSSL", sizeof("OpenSSL")-1) == 0) { /* Old OpenSSL version */ @@ -56,18 +53,15 @@ if test "$PHP_CURL" != "no"; then /* No SSL support */ return 1; ])], - [php_cv_lib_curl_ssl=yes], - [php_cv_lib_curl_ssl=no], - [php_cv_lib_curl_ssl=no]) + [php_cv_lib_curl_ssl_supported=no], + [php_cv_lib_curl_ssl_supported=yes], + [php_cv_lib_curl_ssl_supported=yes]) LIBS=$save_LIBS CFLAGS=$save_CFLAGS ]) - AS_VAR_IF([php_cv_lib_curl_ssl], [yes], [ - AC_DEFINE([HAVE_CURL_OLD_OPENSSL], [1], - [Define to 1 if libcurl is linked against old OpenSSL < 1.1.]) - PHP_SETUP_OPENSSL([CURL_SHARED_LIBADD], - [AC_CHECK_HEADERS([openssl/crypto.h])]) + AS_VAR_IF([php_cv_lib_curl_ssl_supported], [no], [ + AC_MSG_ERROR([libcurl is linked against an unsupported OpenSSL version. OpenSSL 1.1.1 or later is required.]) ]) ]) diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php index cbcb52bc7b0a2..c9cda9c0d4b0c 100644 --- a/ext/curl/curl.stub.php +++ b/ext/curl/curl.stub.php @@ -13,9 +13,9 @@ const CURLOPT_AUTOREFERER = UNKNOWN; /** * @var int - * @deprecated has no effect since 5.1.2 * @cvalue CURLOPT_BINARYTRANSFER */ +#[\Deprecated(since: '8.4', message: 'as it had no effect since 5.1.2')] const CURLOPT_BINARYTRANSFER = UNKNOWN; /** * @var int @@ -3054,6 +3054,13 @@ * @cvalue CURLAUTH_BEARER */ const CURLAUTH_BEARER = UNKNOWN; +#if LIBCURL_VERSION_NUM >= 0x080600 /* Available since 8.6.0 */ +/** + * @var int + * @cvalue CURLINFO_QUEUE_TIME_T + */ +const CURLINFO_QUEUE_TIME_T = UNKNOWN; +#endif /** * @var int * @cvalue CURLINFO_APPCONNECT_TIME_T @@ -3103,6 +3110,13 @@ */ const CURLINFO_POSTTRANSFER_TIME_T = UNKNOWN; #endif +#if LIBCURL_VERSION_NUM >= 0x080200 /* Available since 8.2.0 */ +/** + * @var int + * @cvalue CURLINFO_CONN_ID + */ +const CURLINFO_CONN_ID = UNKNOWN; +#endif /** * @var int * @cvalue CURLOPT_DISALLOW_USERNAME_IN_URL @@ -3325,6 +3339,13 @@ * @cvalue CURLOPT_SSL_EC_CURVES */ const CURLOPT_SSL_EC_CURVES = UNKNOWN; +#if LIBCURL_VERSION_NUM >= 0x080e00 /* Available since 8.14.0 */ +/** + * @var int + * @cvalue CURLOPT_SSL_SIGNATURE_ALGORITHMS + */ +const CURLOPT_SSL_SIGNATURE_ALGORITHMS = UNKNOWN; +#endif /** * @var int * @cvalue CURLPX_BAD_ADDRESS_TYPE @@ -3719,6 +3740,7 @@ final class CurlSharePersistentHandle public readonly array $options; } +#[\Deprecated(since: '8.5', message: "as it has no effect since PHP 8.0")] function curl_close(CurlHandle $handle): void {} /** @refcount 1 */ @@ -3789,6 +3811,7 @@ function curl_setopt_array(CurlHandle $handle, array $options): bool {} function curl_setopt(CurlHandle $handle, int $option, mixed $value): bool {} +#[\Deprecated(since: '8.5', message: "as it has no effect since PHP 8.0")] function curl_share_close(CurlShareHandle $share_handle): void {} function curl_share_errno(CurlShareHandle $share_handle): int {} diff --git a/ext/curl/curl_arginfo.h b/ext/curl/curl_arginfo.h index ef267cd803ba2..b511ff077de9d 100644 --- a/ext/curl/curl_arginfo.h +++ b/ext/curl/curl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 792cdfa8a8ce190d73dffe679c51a41a2ee46cd7 */ + * Stub hash: 2a2772e99deea07c0bc148e9715e6a960230cf4d */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_close, 0, 1, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) @@ -185,7 +185,7 @@ ZEND_FUNCTION(curl_strerror); ZEND_FUNCTION(curl_version); static const zend_function_entry ext_functions[] = { - ZEND_FE(curl_close, arginfo_curl_close) + ZEND_RAW_FENTRY("curl_close", zif_curl_close, arginfo_curl_close, ZEND_ACC_DEPRECATED, NULL, NULL) ZEND_FE(curl_copy_handle, arginfo_curl_copy_handle) ZEND_FE(curl_errno, arginfo_curl_errno) ZEND_FE(curl_error, arginfo_curl_error) @@ -214,7 +214,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(curl_reset, arginfo_curl_reset) ZEND_FE(curl_setopt_array, arginfo_curl_setopt_array) ZEND_FE(curl_setopt, arginfo_curl_setopt) - ZEND_FE(curl_share_close, arginfo_curl_share_close) + ZEND_RAW_FENTRY("curl_share_close", zif_curl_share_close, arginfo_curl_share_close, ZEND_ACC_DEPRECATED, NULL, NULL) ZEND_FE(curl_share_errno, arginfo_curl_share_errno) ZEND_FE(curl_share_init, arginfo_curl_share_init) ZEND_FE(curl_share_setopt, arginfo_curl_share_setopt) @@ -228,7 +228,7 @@ static const zend_function_entry ext_functions[] = { static void register_curl_symbols(int module_number) { REGISTER_LONG_CONSTANT("CURLOPT_AUTOREFERER", CURLOPT_AUTOREFERER, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("CURLOPT_BINARYTRANSFER", CURLOPT_BINARYTRANSFER, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_CURLOPT_BINARYTRANSFER = REGISTER_LONG_CONSTANT("CURLOPT_BINARYTRANSFER", CURLOPT_BINARYTRANSFER, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("CURLOPT_BUFFERSIZE", CURLOPT_BUFFERSIZE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_CAINFO", CURLOPT_CAINFO, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_CAPATH", CURLOPT_CAPATH, CONST_PERSISTENT); @@ -812,6 +812,9 @@ static void register_curl_symbols(int module_number) REGISTER_LONG_CONSTANT("CURLOPT_HAPROXYPROTOCOL", CURLOPT_HAPROXYPROTOCOL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURL_LOCK_DATA_PSL", CURL_LOCK_DATA_PSL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLAUTH_BEARER", CURLAUTH_BEARER, CONST_PERSISTENT); +#if LIBCURL_VERSION_NUM >= 0x080600 /* Available since 8.6.0 */ + REGISTER_LONG_CONSTANT("CURLINFO_QUEUE_TIME_T", CURLINFO_QUEUE_TIME_T, CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("CURLINFO_APPCONNECT_TIME_T", CURLINFO_APPCONNECT_TIME_T, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLINFO_CONNECT_TIME_T", CURLINFO_CONNECT_TIME_T, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLINFO_NAMELOOKUP_TIME_T", CURLINFO_NAMELOOKUP_TIME_T, CONST_PERSISTENT); @@ -824,6 +827,9 @@ static void register_curl_symbols(int module_number) #endif #if LIBCURL_VERSION_NUM >= 0x080a00 /* Available since 8.10.0 */ REGISTER_LONG_CONSTANT("CURLINFO_POSTTRANSFER_TIME_T", CURLINFO_POSTTRANSFER_TIME_T, CONST_PERSISTENT); +#endif +#if LIBCURL_VERSION_NUM >= 0x080200 /* Available since 8.2.0 */ + REGISTER_LONG_CONSTANT("CURLINFO_CONN_ID", CURLINFO_CONN_ID, CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("CURLOPT_DISALLOW_USERNAME_IN_URL", CURLOPT_DISALLOW_USERNAME_IN_URL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_PROXY_TLS13_CIPHERS", CURLOPT_PROXY_TLS13_CIPHERS, CONST_PERSISTENT); @@ -885,6 +891,11 @@ static void register_curl_symbols(int module_number) REGISTER_LONG_CONSTANT("CURLE_PROXY", CURLE_PROXY, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLINFO_PROXY_ERROR", CURLINFO_PROXY_ERROR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_SSL_EC_CURVES", CURLOPT_SSL_EC_CURVES, CONST_PERSISTENT); +#endif +#if LIBCURL_VERSION_NUM >= 0x074900 /* Available since 7.73.0 */ && LIBCURL_VERSION_NUM >= 0x080e00 /* Available since 8.14.0 */ + REGISTER_LONG_CONSTANT("CURLOPT_SSL_SIGNATURE_ALGORITHMS", CURLOPT_SSL_SIGNATURE_ALGORITHMS, CONST_PERSISTENT); +#endif +#if LIBCURL_VERSION_NUM >= 0x074900 /* Available since 7.73.0 */ REGISTER_LONG_CONSTANT("CURLPX_BAD_ADDRESS_TYPE", CURLPX_BAD_ADDRESS_TYPE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLPX_BAD_VERSION", CURLPX_BAD_VERSION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLPX_CLOSED", CURLPX_CLOSED, CONST_PERSISTENT); @@ -973,6 +984,27 @@ static void register_curl_symbols(int module_number) REGISTER_LONG_CONSTANT("CURL_HTTP_VERSION_3ONLY", CURL_HTTP_VERSION_3ONLY, CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("CURLOPT_SAFE_UPLOAD", CURLOPT_SAFE_UPLOAD, CONST_PERSISTENT); + + + zend_attribute *attribute_Deprecated_func_curl_close_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "curl_close", sizeof("curl_close") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_curl_close_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_curl_close_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_curl_close_0_arg1_str = zend_string_init("as it has no effect since PHP 8.0", strlen("as it has no effect since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_func_curl_close_0->args[1].value, attribute_Deprecated_func_curl_close_0_arg1_str); + attribute_Deprecated_func_curl_close_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_curl_share_close_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "curl_share_close", sizeof("curl_share_close") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_curl_share_close_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_curl_share_close_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_func_curl_share_close_0->args[1].value, attribute_Deprecated_func_curl_close_0_arg1_str); + attribute_Deprecated_func_curl_share_close_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0 = zend_add_global_constant_attribute(const_CURLOPT_BINARYTRANSFER, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0_arg1_str = zend_string_init("as it had no effect since 5.1.2", strlen("as it had no effect since 5.1.2"), 1); + ZVAL_STR(&attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0->args[1].value, attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0_arg1_str); + attribute_Deprecated_const_CURLOPT_BINARYTRANSFER_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_CurlHandle(void) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 710f98a13fbb0..e9e9cd5e409af 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -39,20 +39,6 @@ #define HttpPost curl_httppost #endif -/* {{{ cruft for thread safe SSL crypto locks */ -#if defined(ZTS) && defined(HAVE_CURL_OLD_OPENSSL) -# if defined(HAVE_OPENSSL_CRYPTO_H) -# define PHP_CURL_NEED_OPENSSL_TSL -# include -# else -# warning \ - "libcurl was compiled with OpenSSL support, but configure could not find " \ - "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \ - "cause random crashes on SSL requests" -# endif -#endif /* ZTS && HAVE_CURL_OLD_OPENSSL */ -/* }}} */ - #include "zend_smart_str.h" #include "ext/standard/info.h" #include "ext/standard/file.h" @@ -65,31 +51,11 @@ # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif +#include "zend_attributes.h" #include "curl_arginfo.h" ZEND_DECLARE_MODULE_GLOBALS(curl) -#ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */ -static MUTEX_T *php_curl_openssl_tsl = NULL; - -/* Locking callbacks are no longer used since OpenSSL 1.1. Mark the functions as unused to - * avoid warnings due to this. */ -static ZEND_ATTRIBUTE_UNUSED void php_curl_ssl_lock(int mode, int n, const char * file, int line) -{ - if (mode & CRYPTO_LOCK) { - tsrm_mutex_lock(php_curl_openssl_tsl[n]); - } else { - tsrm_mutex_unlock(php_curl_openssl_tsl[n]); - } -} - -static ZEND_ATTRIBUTE_UNUSED unsigned long php_curl_ssl_id(void) -{ - return (unsigned long) tsrm_thread_id(); -} -#endif -/* }}} */ - #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v); #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s) - 1, (double) v); #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s) - 1, (char *) (v ? v : "")); @@ -388,24 +354,6 @@ PHP_MINIT_FUNCTION(curl) register_curl_symbols(module_number); -#ifdef PHP_CURL_NEED_OPENSSL_TSL - if (!CRYPTO_get_id_callback()) { - int i, c = CRYPTO_num_locks(); - - php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T)); - if (!php_curl_openssl_tsl) { - return FAILURE; - } - - for (i = 0; i < c; ++i) { - php_curl_openssl_tsl[i] = tsrm_mutex_alloc(); - } - - CRYPTO_set_id_callback(php_curl_ssl_id); - CRYPTO_set_locking_callback(php_curl_ssl_lock); - } -#endif - if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) { return FAILURE; } @@ -475,7 +423,7 @@ static zend_object *curl_clone_obj(zend_object *object) { clone_ch->cp = cp; _php_setup_easy_copy_handlers(clone_ch, ch); - postfields = &clone_ch->postfields; + postfields = &ch->postfields; if (Z_TYPE_P(postfields) != IS_UNDEF) { if (build_mime_structure_from_hash(clone_ch, postfields) == FAILURE) { zend_throw_exception(NULL, "Failed to clone CurlHandle", 0); @@ -567,21 +515,6 @@ zend_result curl_cast_object(zend_object *obj, zval *result, int type) PHP_MSHUTDOWN_FUNCTION(curl) { curl_global_cleanup(); -#ifdef PHP_CURL_NEED_OPENSSL_TSL - if (php_curl_openssl_tsl) { - int i, c = CRYPTO_num_locks(); - - CRYPTO_set_id_callback(NULL); - CRYPTO_set_locking_callback(NULL); - - for (i = 0; i < c; ++i) { - tsrm_mutex_free(php_curl_openssl_tsl[i]); - } - - free(php_curl_openssl_tsl); - php_curl_openssl_tsl = NULL; - } -#endif UNREGISTER_INI_ENTRIES(); return SUCCESS; } @@ -667,10 +600,10 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string) /* }}} */ /* {{{ curl_progress */ -static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) +static int curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { php_curl *ch = (php_curl *)clientp; - size_t rval = 0; + int rval = 0; #if PHP_CURL_DEBUG fprintf(stderr, "curl_progress() called\n"); @@ -705,10 +638,10 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double /* }}} */ /* {{{ curl_xferinfo */ -static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +static int curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { php_curl *ch = (php_curl *)clientp; - size_t rval = 0; + int rval = 0; #if PHP_CURL_DEBUG fprintf(stderr, "curl_xferinfo() called\n"); @@ -1212,8 +1145,8 @@ static void _php_curl_set_default_options(php_curl *ch) { char *cainfo; - curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); + curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0L); curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write); curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); @@ -1221,8 +1154,8 @@ static void _php_curl_set_default_options(php_curl *ch) curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_header); curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); - curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120); - curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */ + curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120L); + curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20L); /* prevent infinite redirects */ cainfo = INI_STR("openssl.cafile"); if (!(cainfo && cainfo[0] != '\0')) { @@ -1411,7 +1344,6 @@ static inline CURLcode add_simple_field(curl_mime *mime, zend_string *string_key part = curl_mime_addpart(mime); if (part == NULL) { zend_tmp_string_release(tmp_postval); - zend_string_release_ex(string_key, 0); return CURLE_OUT_OF_MEMORY; } if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK @@ -2012,6 +1944,9 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_USERPWD: case CURLOPT_USERNAME: case CURLOPT_PASSWORD: +#if LIBCURL_VERSION_NUM >= 0x080e00 /* Available since 8.14.0 */ + case CURLOPT_SSL_SIGNATURE_ALGORITHMS: +#endif { if (Z_ISNULL_P(zvalue)) { error = curl_easy_setopt(ch->cp, option, NULL); @@ -2234,7 +2169,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue /* no need to build the mime structure for empty hashtables; also works around https://github.com/curl/curl/issues/6455 */ curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, ""); - error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, 0); + error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, 0L); } else { return build_mime_structure_from_hash(ch, zvalue); } @@ -2268,7 +2203,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_POSTREDIR: lval = zval_get_long(zvalue); - error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, lval & CURL_REDIR_POST_ALL); + error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, (long) (lval & CURL_REDIR_POST_ALL)); break; /* the following options deal with files, therefore the open_basedir check @@ -2308,11 +2243,11 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue if (zend_is_true(zvalue)) { curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug); curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1L); } else { curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL); curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0L); } break; @@ -2639,6 +2574,11 @@ PHP_FUNCTION(curl_getinfo) if (curl_easy_getinfo(ch->cp, CURLINFO_APPCONNECT_TIME_T, &co) == CURLE_OK) { CAAL("appconnect_time_us", co); } +#if LIBCURL_VERSION_NUM >= 0x080600 /* Available since 8.6.0 */ + if (curl_easy_getinfo(ch->cp, CURLINFO_QUEUE_TIME_T , &co) == CURLE_OK) { + CAAL("queue_time_us", co); + } +#endif if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME_T, &co) == CURLE_OK) { CAAL("connect_time_us", co); } @@ -2690,6 +2630,11 @@ PHP_FUNCTION(curl_getinfo) if (curl_easy_getinfo(ch->cp, CURLINFO_PROXYAUTH_USED, &l_code) == CURLE_OK) { CAAL("proxyauth_used", l_code); } +#endif +#if LIBCURL_VERSION_NUM >= 0x080200 /* Available since 8.2.0 */ + if (curl_easy_getinfo(ch->cp, CURLINFO_CONN_ID , &co) == CURLE_OK) { + CAAL("conn_id", co); + } #endif } else { switch (option) { diff --git a/ext/curl/tests/Caddyfile b/ext/curl/tests/Caddyfile index ceba97ee93971..f6f4279af8949 100644 --- a/ext/curl/tests/Caddyfile +++ b/ext/curl/tests/Caddyfile @@ -21,3 +21,8 @@ basic_auth /http-basic-auth { # bcrypt password hash for "password", calculated with 'caddy hash-password' user $2a$14$yUKl9SGqVTAAqPTzLup.DefsbXXx3kfreNnzpJOUHcIrKnr5lgef2 } + +route /ping { + templates + respond `pong` +} diff --git a/ext/curl/tests/bug27023.phpt b/ext/curl/tests/bug27023.phpt index 7d6850d75ccb3..7b8ddf6d92b06 100644 --- a/ext/curl/tests/bug27023.phpt +++ b/ext/curl/tests/bug27023.phpt @@ -33,9 +33,6 @@ $file = curl_file_create(__DIR__ . '/curl_testdata1.txt', "text/plain", "foo.txt $params = array('file' => $file); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); var_dump(curl_exec($ch)); - - -curl_close($ch); ?> --EXPECTF-- string(%d) "curl_testdata1.txt|application/octet-stream|6" diff --git a/ext/curl/tests/bug46711.phpt b/ext/curl/tests/bug46711.phpt index a0b211a7876ab..0540a79bca5b3 100644 --- a/ext/curl/tests/bug46711.phpt +++ b/ext/curl/tests/bug46711.phpt @@ -21,7 +21,7 @@ var_dump($opt); // with this bug, $opt[58] becomes NULL ?> --EXPECTF-- -Deprecated: Constant CURLOPT_BINARYTRANSFER is deprecated in %s on line %d +Deprecated: Constant CURLOPT_BINARYTRANSFER is deprecated since 8.4, as it had no effect since 5.1.2 in %s on line %d array(2) { [58]=> bool(true) diff --git a/ext/curl/tests/bug48203.phpt b/ext/curl/tests/bug48203.phpt index 1f1423cbee9f5..23d61964b5e5a 100644 --- a/ext/curl/tests/bug48203.phpt +++ b/ext/curl/tests/bug48203.phpt @@ -16,7 +16,6 @@ curl_setopt($ch, CURLOPT_URL, curl_cli_server_start()); fclose($fp); // <-- premature close of $fp caused a crash! curl_exec($ch); -curl_close($ch); echo "Ok\n"; diff --git a/ext/curl/tests/bug48207.phpt b/ext/curl/tests/bug48207.phpt index 982744c785231..086f949ff63d8 100644 --- a/ext/curl/tests/bug48207.phpt +++ b/ext/curl/tests/bug48207.phpt @@ -43,7 +43,6 @@ try { } curl_exec($ch); -curl_close($ch); is_file($tempfile) and @unlink($tempfile); isset($tempname) and is_file($tempname) and @unlink($tempname); ?> diff --git a/ext/curl/tests/bug54798-unix.phpt b/ext/curl/tests/bug54798-unix.phpt index 6eb5099b31b2e..6bbca3375ed5d 100644 --- a/ext/curl/tests/bug54798-unix.phpt +++ b/ext/curl/tests/bug54798-unix.phpt @@ -34,8 +34,6 @@ function checkForClosedFilePointer($host, $curl_option, $description) { curl_exec($ch); - curl_close($ch); - echo "Ok for $description\n"; } diff --git a/ext/curl/tests/bug54798.phpt b/ext/curl/tests/bug54798.phpt index 4403b5212aa4b..da38b72d775b0 100644 --- a/ext/curl/tests/bug54798.phpt +++ b/ext/curl/tests/bug54798.phpt @@ -28,8 +28,6 @@ function checkForClosedFilePointer($host, $curl_option, $description) { curl_exec($ch); - curl_close($ch); - echo "Ok for $description\n"; } diff --git a/ext/curl/tests/bug55767.phpt b/ext/curl/tests/bug55767.phpt index a57da6e6d88f4..50572f295f7e4 100644 --- a/ext/curl/tests/bug55767.phpt +++ b/ext/curl/tests/bug55767.phpt @@ -20,7 +20,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/bug61948-unix.phpt b/ext/curl/tests/bug61948-unix.phpt index 0b5d9b85989b7..09c7c3ecb9e71 100644 --- a/ext/curl/tests/bug61948-unix.phpt +++ b/ext/curl/tests/bug61948-unix.phpt @@ -14,7 +14,6 @@ open_basedir="/tmp" var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "")); var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/foo")); var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "/xxx/bar")); - curl_close($ch); ?> --EXPECTF-- bool(true) diff --git a/ext/curl/tests/bug61948.phpt b/ext/curl/tests/bug61948.phpt index 1245c3a69998f..80941344f0c8f 100644 --- a/ext/curl/tests/bug61948.phpt +++ b/ext/curl/tests/bug61948.phpt @@ -13,7 +13,6 @@ curl var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "")); var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "$base_dir/foo")); var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "c:/xxx/bar")); - curl_close($ch); ?> --CLEAN-- --EXPECTF-- bool(true) diff --git a/ext/curl/tests/bug65458.phpt b/ext/curl/tests/bug65458.phpt index f19e7a289a444..83b46057a3751 100644 --- a/ext/curl/tests/bug65458.phpt +++ b/ext/curl/tests/bug65458.phpt @@ -11,7 +11,7 @@ for ($i = 0; $i < 10000; $i++) { } $preclose = memory_get_usage(); -curl_close($ch); +$ch = null; // This is a slightly tricky heuristic, but basically, we want to ensure // $preclose - $init has a delta in the order of bytes, not megabytes. Given diff --git a/ext/curl/tests/bug65646.phpt b/ext/curl/tests/bug65646.phpt index 1c9f602367c48..2f83b7f5afa81 100644 --- a/ext/curl/tests/bug65646.phpt +++ b/ext/curl/tests/bug65646.phpt @@ -10,7 +10,6 @@ if (ini_get('open_basedir')) exit("skip open_basedir is set"); --EXPECT-- bool(true) diff --git a/ext/curl/tests/bug65646_open_basedir_new.phpt b/ext/curl/tests/bug65646_open_basedir_new.phpt index 5ea40252f9aa2..80d6c7ffbf725 100644 --- a/ext/curl/tests/bug65646_open_basedir_new.phpt +++ b/ext/curl/tests/bug65646_open_basedir_new.phpt @@ -10,7 +10,6 @@ $ch = curl_init(); var_dump(curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)); var_dump(curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_FILE)); var_dump(curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_FILE)); -curl_close($ch); ?> --EXPECTF-- bool(true) diff --git a/ext/curl/tests/bug66109.phpt b/ext/curl/tests/bug66109.phpt index 48fcfb4beed61..623ad20f863a9 100644 --- a/ext/curl/tests/bug66109.phpt +++ b/ext/curl/tests/bug66109.phpt @@ -15,9 +15,6 @@ var_dump(curl_exec($ch)); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, NULL); var_dump(curl_exec($ch)); - -curl_close($ch); - ?> --EXPECT-- string(6) "DELETE" diff --git a/ext/curl/tests/bug68937.phpt b/ext/curl/tests/bug68937.phpt index 7c42483f9faec..884947b8c454b 100644 --- a/ext/curl/tests/bug68937.phpt +++ b/ext/curl/tests/bug68937.phpt @@ -31,7 +31,6 @@ function curl_read($ch, $fp, $len) { } curl_exec($ch); -curl_close($ch); ?> --EXPECT-- NULL diff --git a/ext/curl/tests/bug68937_2.phpt b/ext/curl/tests/bug68937_2.phpt index 596bbfa4b3775..7ae67acf00a35 100644 --- a/ext/curl/tests/bug68937_2.phpt +++ b/ext/curl/tests/bug68937_2.phpt @@ -31,7 +31,6 @@ function curl_read($ch, $fp, $len) { } curl_exec($ch); -curl_close($ch); ?> --EXPECTF-- resource(%d) of type (stream) diff --git a/ext/curl/tests/bug69316.phpt b/ext/curl/tests/bug69316.phpt index 3e0e049d08e1b..2cbcb560d5abd 100644 --- a/ext/curl/tests/bug69316.phpt +++ b/ext/curl/tests/bug69316.phpt @@ -27,7 +27,6 @@ curl curl_setopt($ch, CURLOPT_FILE, $f_file); curl_setopt($ch, CURLOPT_URL, $url); curl_exec($ch); - curl_close($ch); ?> --CLEAN-- $file); var_dump(curl_setopt($ch, CURLOPT_POSTFIELDS, $params)); var_dump(curl_exec($ch)); -curl_close($ch); ?> --EXPECTF-- bool(true) diff --git a/ext/curl/tests/bug77946.phpt b/ext/curl/tests/bug77946.phpt index 7b836187d6bfb..fa871d21cc7bf 100644 --- a/ext/curl/tests/bug77946.phpt +++ b/ext/curl/tests/bug77946.phpt @@ -25,10 +25,6 @@ do { } } while ($status === CURLM_CALL_MULTI_PERFORM || $active); -foreach ($urls as $i => $url) { - curl_close($conn[$i]); -} - curl_multi_close($mh); ?> --EXPECTF-- diff --git a/ext/curl/tests/bug78775.phpt b/ext/curl/tests/bug78775.phpt index 3e2ece284452d..db68c26e6baaf 100644 --- a/ext/curl/tests/bug78775.phpt +++ b/ext/curl/tests/bug78775.phpt @@ -24,7 +24,6 @@ curl_setopt_array( ); var_dump(curl_exec($handle)); -curl_close($handle); fwrite($sock, "GET / HTTP/1.0\n\n"); var_dump(fread($sock, 8)); diff --git a/ext/curl/tests/bug79199.phpt b/ext/curl/tests/bug79199.phpt index c67bfffd5e1dd..9cabe8ac393b1 100644 --- a/ext/curl/tests/bug79199.phpt +++ b/ext/curl/tests/bug79199.phpt @@ -8,8 +8,8 @@ $mem_old = 0; for($i = 0; $i < 50; ++$i) { $c1 = curl_init(); $c2 = curl_copy_handle($c1); - curl_close($c2); - curl_close($c1); + $c2 = null; + $c1 = null; $mem_new = memory_get_usage(); if ($mem_new <= $mem_old) { break; diff --git a/ext/curl/tests/curl_CURLOPT_READDATA.phpt b/ext/curl/tests/curl_CURLOPT_READDATA.phpt index 21d394a674c68..14f2b606fa0d2 100644 --- a/ext/curl/tests/curl_CURLOPT_READDATA.phpt +++ b/ext/curl/tests/curl_CURLOPT_READDATA.phpt @@ -32,8 +32,6 @@ if (false === $response = curl_exec($ch)) { echo $response; } -curl_close($ch); - // Clean the temporary file @unlink($tempname); ?> diff --git a/ext/curl/tests/curl_basic_001.phpt b/ext/curl/tests/curl_basic_001.phpt index f89394acdac55..45ef816b5634f 100644 --- a/ext/curl/tests/curl_basic_001.phpt +++ b/ext/curl/tests/curl_basic_001.phpt @@ -19,7 +19,6 @@ curl ob_start(); // start output buffering curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $ok = curl_exec($ch); - curl_close($ch); $curl_content = ob_get_contents(); ob_end_clean(); diff --git a/ext/curl/tests/curl_basic_002.phpt b/ext/curl/tests/curl_basic_002.phpt index 1b79fc0d6dc0d..5a4dbbef9a5c8 100644 --- a/ext/curl/tests/curl_basic_002.phpt +++ b/ext/curl/tests/curl_basic_002.phpt @@ -21,8 +21,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); - var_dump( $curl_content ); ?> --EXPECT-- diff --git a/ext/curl/tests/curl_basic_003.phpt b/ext/curl/tests/curl_basic_003.phpt index cc578b9b50586..1f3fd07f42877 100644 --- a/ext/curl/tests/curl_basic_003.phpt +++ b/ext/curl/tests/curl_basic_003.phpt @@ -23,8 +23,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); - var_dump( $curl_content ); ?> --EXPECT-- diff --git a/ext/curl/tests/curl_basic_004.phpt b/ext/curl/tests/curl_basic_004.phpt index eb89987a3132b..446d0feb98365 100644 --- a/ext/curl/tests/curl_basic_004.phpt +++ b/ext/curl/tests/curl_basic_004.phpt @@ -22,8 +22,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); - var_dump( $curl_content ); ?> --EXPECT-- diff --git a/ext/curl/tests/curl_basic_005.phpt b/ext/curl/tests/curl_basic_005.phpt index 542e253d53e05..9bcbb5c11bfdd 100644 --- a/ext/curl/tests/curl_basic_005.phpt +++ b/ext/curl/tests/curl_basic_005.phpt @@ -22,8 +22,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); - var_dump( $curl_content ); ?> --EXPECT-- diff --git a/ext/curl/tests/curl_basic_006.phpt b/ext/curl/tests/curl_basic_006.phpt index a39eaa06b7c3d..f0142d8333fda 100644 --- a/ext/curl/tests/curl_basic_006.phpt +++ b/ext/curl/tests/curl_basic_006.phpt @@ -24,7 +24,6 @@ curl }); curl_exec($ch); - curl_close($ch); ob_end_flush(); echo "Data: $alldata"; ?> diff --git a/ext/curl/tests/curl_basic_007.phpt b/ext/curl/tests/curl_basic_007.phpt index 3834e4674f827..1ae0ec72186b6 100644 --- a/ext/curl/tests/curl_basic_007.phpt +++ b/ext/curl/tests/curl_basic_007.phpt @@ -15,9 +15,6 @@ $ch = curl_init(); curl_exec($ch); var_dump(curl_error($ch)); var_dump(curl_errno($ch)); -curl_close($ch); - - ?> --EXPECTF-- string(%d) "No URL set%A" diff --git a/ext/curl/tests/curl_basic_008.phpt b/ext/curl/tests/curl_basic_008.phpt index 353c44327c5e8..d9601dfcac125 100644 --- a/ext/curl/tests/curl_basic_008.phpt +++ b/ext/curl/tests/curl_basic_008.phpt @@ -21,9 +21,6 @@ curl_setopt($ch, CURLOPT_URL, $url); curl_exec($ch); var_dump(curl_error($ch)); var_dump(curl_errno($ch)); -curl_close($ch); - - ?> --EXPECTF-- %s resolve%s diff --git a/ext/curl/tests/curl_basic_009.phpt b/ext/curl/tests/curl_basic_009.phpt index ade7cffcb8289..b6c2b2fd41826 100644 --- a/ext/curl/tests/curl_basic_009.phpt +++ b/ext/curl/tests/curl_basic_009.phpt @@ -15,9 +15,6 @@ curl_setopt($ch, CURLOPT_URL, $url); curl_exec($ch); var_dump(curl_error($ch)); var_dump(curl_errno($ch)); -curl_close($ch); - - ?> --EXPECTF-- string(%d) "%Srotocol%s" diff --git a/ext/curl/tests/curl_basic_010.phpt b/ext/curl/tests/curl_basic_010.phpt index 7920408dc5534..908886b2e8418 100644 --- a/ext/curl/tests/curl_basic_010.phpt +++ b/ext/curl/tests/curl_basic_010.phpt @@ -22,9 +22,6 @@ curl_setopt($ch, CURLOPT_URL, $url); curl_exec($ch); var_dump(curl_error($ch)); var_dump(curl_errno($ch)); -curl_close($ch); - - ?> --EXPECTF-- string(%d) "%r(Couldn't resolve proxy|Could not resolve proxy:|Could not resolve host:|Could not resolve:|Unsupported proxy syntax in)%r %s" diff --git a/ext/curl/tests/curl_basic_011.phpt b/ext/curl/tests/curl_basic_011.phpt index cf8cc63d02f6f..4a70e5cd9f3d9 100644 --- a/ext/curl/tests/curl_basic_011.phpt +++ b/ext/curl/tests/curl_basic_011.phpt @@ -21,7 +21,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_basic_012.phpt b/ext/curl/tests/curl_basic_012.phpt index 9de92898f396b..83c91f657101f 100644 --- a/ext/curl/tests/curl_basic_012.phpt +++ b/ext/curl/tests/curl_basic_012.phpt @@ -21,7 +21,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_basic_013.phpt b/ext/curl/tests/curl_basic_013.phpt index 4b0c46b5183f3..08ed66225b74a 100644 --- a/ext/curl/tests/curl_basic_013.phpt +++ b/ext/curl/tests/curl_basic_013.phpt @@ -21,7 +21,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $curl_content = curl_exec($ch); - curl_close($ch); var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_basic_019.phpt b/ext/curl/tests/curl_basic_019.phpt index 20bddd87210f1..62b519f790ff2 100644 --- a/ext/curl/tests/curl_basic_019.phpt +++ b/ext/curl/tests/curl_basic_019.phpt @@ -16,7 +16,6 @@ curl curl_exec($ch); $info = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); var_dump($url == $info); - curl_close($ch); ?> --EXPECT-- Hello World! diff --git a/ext/curl/tests/curl_basic_020.phpt b/ext/curl/tests/curl_basic_020.phpt index d7f92d3d6662c..0b022d5f7a86e 100644 --- a/ext/curl/tests/curl_basic_020.phpt +++ b/ext/curl/tests/curl_basic_020.phpt @@ -14,7 +14,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); curl_exec($ch); var_dump(curl_getinfo($ch, CURLINFO_HTTP_CODE)); - curl_close($ch); ?> --EXPECT-- Hello World! diff --git a/ext/curl/tests/curl_basic_021.phpt b/ext/curl/tests/curl_basic_021.phpt index d6b31f2c41ab5..6f67ad7fa7e43 100644 --- a/ext/curl/tests/curl_basic_021.phpt +++ b/ext/curl/tests/curl_basic_021.phpt @@ -14,7 +14,6 @@ curl curl_setopt($ch, CURLOPT_URL, $url); curl_exec($ch); var_dump(curl_getinfo($ch, CURLINFO_CONTENT_TYPE)); - curl_close($ch); ?> --EXPECT-- string(24) "text/plain;charset=utf-8" diff --git a/ext/curl/tests/curl_basic_023.phpt b/ext/curl/tests/curl_basic_023.phpt index 28e6dc888ee44..f7b5374858222 100644 --- a/ext/curl/tests/curl_basic_023.phpt +++ b/ext/curl/tests/curl_basic_023.phpt @@ -17,7 +17,6 @@ curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_exec($ch); var_dump(CURL_HTTP_VERSION_1_1 === curl_getinfo($ch, CURLINFO_HTTP_VERSION)); -curl_close($ch); ?> --EXPECT-- bool(true) diff --git a/ext/curl/tests/curl_basic_024.phpt b/ext/curl/tests/curl_basic_024.phpt index d0e85a1204b78..c075fd8747d01 100644 --- a/ext/curl/tests/curl_basic_024.phpt +++ b/ext/curl/tests/curl_basic_024.phpt @@ -17,7 +17,6 @@ curl_exec($ch); var_dump(CURLPROTO_HTTP === curl_getinfo($ch, CURLINFO_PROTOCOL)); var_dump(0 === curl_getinfo($ch, CURLINFO_PROXY_SSL_VERIFYRESULT)); var_dump(curl_getinfo($ch, CURLINFO_SCHEME)); -curl_close($ch); ?> --EXPECTF-- bool(true) diff --git a/ext/curl/tests/curl_basic_025.phpt b/ext/curl/tests/curl_basic_025.phpt index d190d30a067dc..e333c7444e4f5 100644 --- a/ext/curl/tests/curl_basic_025.phpt +++ b/ext/curl/tests/curl_basic_025.phpt @@ -22,7 +22,6 @@ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "data"); curl_exec($ch); var_dump(curl_getinfo($ch, CURLINFO_EFFECTIVE_METHOD)); -curl_close($ch); ?> --EXPECT-- string(4) "POST" diff --git a/ext/curl/tests/curl_basic_026.phpt b/ext/curl/tests/curl_basic_026.phpt index befe9c7e69c18..c8407bb40ef8b 100644 --- a/ext/curl/tests/curl_basic_026.phpt +++ b/ext/curl/tests/curl_basic_026.phpt @@ -21,7 +21,6 @@ curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); var_dump(curl_setopt($ch, CURLOPT_MIME_OPTIONS, CURLMIMEOPT_FORMESCAPE)); curl_exec($ch); -curl_close($ch); ?> --EXPECT-- bool(true) diff --git a/ext/curl/tests/curl_basic_027.phpt b/ext/curl/tests/curl_basic_027.phpt index d4b408859c679..9a7fd0cfafb25 100644 --- a/ext/curl/tests/curl_basic_027.phpt +++ b/ext/curl/tests/curl_basic_027.phpt @@ -29,7 +29,6 @@ var_dump(curl_setopt($ch, CURLOPT_SSH_HOSTKEYFUNCTION, function ($ch, $keytype, return CURLKHMATCH_OK; })); curl_exec($ch); -curl_close($ch); ?> --EXPECT-- bool(true) diff --git a/ext/curl/tests/curl_basic_028.phpt b/ext/curl/tests/curl_basic_028.phpt index f8e79f63ead5e..0c9eb8b38de14 100644 --- a/ext/curl/tests/curl_basic_028.phpt +++ b/ext/curl/tests/curl_basic_028.phpt @@ -25,7 +25,6 @@ var_dump(curl_setopt($ch, CURLOPT_PROTOCOLS_STR, "FilE,DICT")); var_dump(curl_setopt($ch, CURLOPT_PROTOCOLS_STR, "DICT")); var_dump(curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS_STR, "HTTP")); curl_exec($ch); -curl_close($ch); ?> --EXPECTF-- Warning: curl_setopt(): The FILE protocol cannot be activated when an open_basedir is set in %s on line %d diff --git a/ext/curl/tests/curl_basic_029.phpt b/ext/curl/tests/curl_basic_029.phpt index b43e5e3897dd6..7e2ba34c72ca6 100644 --- a/ext/curl/tests/curl_basic_029.phpt +++ b/ext/curl/tests/curl_basic_029.phpt @@ -23,7 +23,6 @@ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); var_dump(curl_setopt($ch, CURLOPT_WS_OPTIONS, 0)); var_dump(curl_setopt($ch, CURLOPT_WS_OPTIONS, CURLWS_RAW_MODE)); curl_exec($ch); -curl_close($ch); ?> --EXPECTF-- bool(%s) diff --git a/ext/curl/tests/curl_basic_030.phpt b/ext/curl/tests/curl_basic_030.phpt index 0beace9a7eac3..c0285b873e136 100644 --- a/ext/curl/tests/curl_basic_030.phpt +++ b/ext/curl/tests/curl_basic_030.phpt @@ -22,7 +22,6 @@ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); var_dump(curl_setopt($ch, CURLOPT_CA_CACHE_TIMEOUT, 1)); var_dump(curl_setopt($ch, CURLOPT_QUICK_EXIT, 1000)); curl_exec($ch); -curl_close($ch); ?> --EXPECT-- bool(true) diff --git a/ext/curl/tests/curl_close_basic.phpt b/ext/curl/tests/curl_close_basic.phpt index 5b327264c7ded..11d4b3a8387c1 100644 --- a/ext/curl/tests/curl_close_basic.phpt +++ b/ext/curl/tests/curl_close_basic.phpt @@ -11,6 +11,7 @@ $ch = curl_init(); curl_close($ch); var_dump($ch); ?> ---EXPECT-- -object(CurlHandle)#1 (0) { +--EXPECTF-- +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d +object(CurlHandle)#%d (0) { } diff --git a/ext/curl/tests/curl_copy_handle_basic_001.phpt b/ext/curl/tests/curl_copy_handle_basic_001.phpt index 527c818325115..e118e94e2b5bc 100644 --- a/ext/curl/tests/curl_copy_handle_basic_001.phpt +++ b/ext/curl/tests/curl_copy_handle_basic_001.phpt @@ -21,10 +21,9 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $copy = curl_copy_handle($ch); - curl_close($ch); + $ch = null; $curl_content = curl_exec($copy); - curl_close($copy); var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_copy_handle_basic_002.phpt b/ext/curl/tests/curl_copy_handle_basic_002.phpt index 8976433de2d59..efd03a561145f 100644 --- a/ext/curl/tests/curl_copy_handle_basic_002.phpt +++ b/ext/curl/tests/curl_copy_handle_basic_002.phpt @@ -22,10 +22,9 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $copy = curl_copy_handle($ch); - curl_close($ch); + $ch = null; $curl_content = curl_exec($copy); - curl_close($copy); var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_copy_handle_basic_004.phpt b/ext/curl/tests/curl_copy_handle_basic_004.phpt index be0c4e3462374..2293c4403eb45 100644 --- a/ext/curl/tests/curl_copy_handle_basic_004.phpt +++ b/ext/curl/tests/curl_copy_handle_basic_004.phpt @@ -23,10 +23,9 @@ curl $curl_content = curl_exec($ch); $copy = curl_copy_handle($ch); - curl_close($ch); + $ch = null; $curl_content_copy = curl_exec($copy); - curl_close($copy); var_dump( $curl_content_copy ); ?> diff --git a/ext/curl/tests/curl_copy_handle_basic_005.phpt b/ext/curl/tests/curl_copy_handle_basic_005.phpt index 1b5f10034c29f..2eff46839e490 100644 --- a/ext/curl/tests/curl_copy_handle_basic_005.phpt +++ b/ext/curl/tests/curl_copy_handle_basic_005.phpt @@ -25,10 +25,9 @@ curl $curl_content = curl_exec($ch); $copy = curl_copy_handle($ch); - curl_close($ch); + $ch = null; $curl_content_copy = curl_exec($copy); - curl_close($copy); var_dump( $curl_content_copy ); ?> diff --git a/ext/curl/tests/curl_copy_handle_basic_006.phpt b/ext/curl/tests/curl_copy_handle_basic_006.phpt index 5d35058432274..aa0bff4ae9b93 100644 --- a/ext/curl/tests/curl_copy_handle_basic_006.phpt +++ b/ext/curl/tests/curl_copy_handle_basic_006.phpt @@ -30,7 +30,11 @@ curl curl_close($copy); ?> ---EXPECT-- +--EXPECTF-- *** Testing curl copy handle with User Agent *** string(9) "cURL phpt" string(9) "cURL phpt" + +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d + +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d diff --git a/ext/curl/tests/curl_copy_handle_basic_007.phpt b/ext/curl/tests/curl_copy_handle_basic_007.phpt index 16be071ae0004..800b4df16addf 100644 --- a/ext/curl/tests/curl_copy_handle_basic_007.phpt +++ b/ext/curl/tests/curl_copy_handle_basic_007.phpt @@ -20,10 +20,9 @@ curl curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use $copy = curl_copy_handle($ch); - curl_close($ch); + $ch = null; $curl_content = curl_exec($copy); - curl_close($copy); var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_copy_handle_variation3.phpt b/ext/curl/tests/curl_copy_handle_variation3.phpt index a766496d98841..2e57dafa18dee 100644 --- a/ext/curl/tests/curl_copy_handle_variation3.phpt +++ b/ext/curl/tests/curl_copy_handle_variation3.phpt @@ -29,7 +29,11 @@ curl_close($ch2); --EXPECTF-- bool(true) string(%d) "curl_copy_handle_variation3.txt|application/octet-stream|5" + +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d string(%d) "curl_copy_handle_variation3.txt|application/octet-stream|5" + +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d --CLEAN-- $file); +var_dump(curl_setopt($ch1, CURLOPT_POSTFIELDS, $params)); + +$ch2 = clone($ch1); + +var_dump(curl_exec($ch1)); + +var_dump(curl_exec($ch2)); +?> +--EXPECTF-- +bool(true) +string(%d) "curl_copy_handle_variation3_clone.txt|application/octet-stream|5" +string(%d) "curl_copy_handle_variation3_clone.txt|application/octet-stream|5" +--CLEAN-- + diff --git a/ext/curl/tests/curl_copy_handle_variation5.phpt b/ext/curl/tests/curl_copy_handle_variation5.phpt index 5549c27d1a178..dada18e6f60a0 100644 --- a/ext/curl/tests/curl_copy_handle_variation5.phpt +++ b/ext/curl/tests/curl_copy_handle_variation5.phpt @@ -42,8 +42,14 @@ curl_close($ch3); bool(true) bool(true) string(%d) "abc.txt|application/octet-stream|5" + +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d string(%d) "def.txt|application/octet-stream|11" + +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d string(%d) "def.txt|application/octet-stream|11" + +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d ===DONE=== --CLEAN-- --EXPECTF-- == Testing curl_error with a fake URL == diff --git a/ext/curl/tests/curl_file_deleted_before_curl_close.phpt b/ext/curl/tests/curl_file_deleted_before_curl_close.phpt index 17a3b476f4476..384be513f330b 100644 --- a/ext/curl/tests/curl_file_deleted_before_curl_close.phpt +++ b/ext/curl/tests/curl_file_deleted_before_curl_close.phpt @@ -35,5 +35,6 @@ echo "Closed correctly\n"; ---EXPECT-- +--EXPECTF-- +Deprecated: Function curl_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d Closed correctly diff --git a/ext/curl/tests/curl_file_upload.phpt b/ext/curl/tests/curl_file_upload.phpt index 75aba7d90e822..8b85190ff41e6 100644 --- a/ext/curl/tests/curl_file_upload.phpt +++ b/ext/curl/tests/curl_file_upload.phpt @@ -61,8 +61,6 @@ curl_setopt($ch, CURLOPT_URL, "{$host}/get.inc?test=post"); $params = array('file' => '@' . __DIR__ . '/curl_testdata1.txt'); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); var_dump(curl_exec($ch)); - -curl_close($ch); ?> --EXPECTF-- string(%d) "curl_testdata1.txt|application/octet-stream|6" diff --git a/ext/curl/tests/curl_file_upload_stream.phpt b/ext/curl/tests/curl_file_upload_stream.phpt index 7a99eac518d23..967e711bc4829 100644 --- a/ext/curl/tests/curl_file_upload_stream.phpt +++ b/ext/curl/tests/curl_file_upload_stream.phpt @@ -17,7 +17,6 @@ $params = array('file' => $file); var_dump(curl_setopt($ch, CURLOPT_POSTFIELDS, $params)); var_dump(curl_exec($ch)); -curl_close($ch); ?> --EXPECT-- bool(true) diff --git a/ext/curl/tests/curl_ftp_pasv.phpt b/ext/curl/tests/curl_ftp_pasv.phpt index f8fddd574cb40..59937cf7a6210 100644 --- a/ext/curl/tests/curl_ftp_pasv.phpt +++ b/ext/curl/tests/curl_ftp_pasv.phpt @@ -50,8 +50,6 @@ if (false === getenv('PHP_CURL_FTP_REMOTE_PASSWD')) exit("skip PHP_CURL_FTP_REM $result = curl_exec ( $ch ); var_dump ( $result ); - curl_close ( $ch ); - ?> --EXPECT-- bool(true) diff --git a/ext/curl/tests/curl_getinfo_CURLINFO_CONN_ID.phpt b/ext/curl/tests/curl_getinfo_CURLINFO_CONN_ID.phpt new file mode 100644 index 0000000000000..4a90b0a3c52e3 --- /dev/null +++ b/ext/curl/tests/curl_getinfo_CURLINFO_CONN_ID.phpt @@ -0,0 +1,146 @@ +--TEST-- +Curlinfo CURLINFO_CONN_ID +--EXTENSIONS-- +curl +--SKIPIF-- += 8.2.0"); +?> +--FILE-- +0); + +foreach([$ch1, $ch2] as $key => $ch) { + $result = curl_multi_getcontent($ch); + $info = curl_getinfo($ch); + var_dump(isset($info['conn_id'])); + var_dump(is_int($info['conn_id'])); + var_dump(curl_getinfo($ch, CURLINFO_CONN_ID) === $info['conn_id']); + var_dump(curl_getinfo($ch, CURLINFO_CONN_ID) === $key); +} + +$csh = curl_share_init(); + +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); + + +$ch1=curl_init(); +$ch2=curl_init(); + +foreach([$ch1, $ch2] as $ch) { + curl_setopt($ch, CURLOPT_URL, "{$host}/get.inc?test=getpost&get_param=Curl%20Handle"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $info = curl_getinfo($ch); + var_dump(isset($info['conn_id'])); + var_dump($info['conn_id'] === -1); +} + + +curl_setopt($ch1, CURLOPT_SHARE, $csh); + +$result = curl_exec($ch1); + +$info = curl_getinfo($ch1); +var_dump(isset($info['conn_id'])); +var_dump(is_int($info['conn_id'])); +var_dump(curl_getinfo($ch1, CURLINFO_CONN_ID) === $info['conn_id']); +var_dump(curl_getinfo($ch1, CURLINFO_CONN_ID) === 0); + +curl_setopt($ch2, CURLOPT_SHARE, $csh); + +$result = curl_exec($ch2); + +$info = curl_getinfo($ch2); +var_dump(isset($info['conn_id'])); +var_dump(is_int($info['conn_id'])); +var_dump(curl_getinfo($ch2, CURLINFO_CONN_ID) === $info['conn_id']); +var_dump(curl_getinfo($ch2, CURLINFO_CONN_ID) === 1); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) + diff --git a/ext/curl/tests/curl_getinfo_CURLINFO_QUEUE_TIME_T.phpt b/ext/curl/tests/curl_getinfo_CURLINFO_QUEUE_TIME_T.phpt new file mode 100644 index 0000000000000..82064b93af182 --- /dev/null +++ b/ext/curl/tests/curl_getinfo_CURLINFO_QUEUE_TIME_T.phpt @@ -0,0 +1,41 @@ +--TEST-- +Curlinfo CURLINFO_QUEUE_TIME_T +--EXTENSIONS-- +curl +--SKIPIF-- += 8.6.0"); +?> +--FILE-- + 0); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) + diff --git a/ext/curl/tests/curl_multi_info_read.phpt b/ext/curl/tests/curl_multi_info_read.phpt index de203cbd5aa32..32de1b9912edb 100644 --- a/ext/curl/tests/curl_multi_info_read.phpt +++ b/ext/curl/tests/curl_multi_info_read.phpt @@ -25,10 +25,6 @@ do { while ($info = curl_multi_info_read($mh)) { var_dump($info); } - -foreach ($urls as $i => $url) { - curl_close($conn[$i]); -} ?> --EXPECTF-- array(3) { diff --git a/ext/curl/tests/curl_multi_segfault.phpt b/ext/curl/tests/curl_multi_segfault.phpt index 06fc7484cb5f9..025f71ee31d03 100644 --- a/ext/curl/tests/curl_multi_segfault.phpt +++ b/ext/curl/tests/curl_multi_segfault.phpt @@ -47,7 +47,6 @@ if (false === getenv('PHP_CURL_FTP_REMOTE_PASSWD')) exit("skip PHP_CURL_FTP_REM var_dump(is_string(curl_multi_getcontent($ch))); curl_multi_remove_handle($cmh, $ch); - curl_close($ch); curl_multi_close($cmh); ?> --EXPECT-- diff --git a/ext/curl/tests/curl_postfields_array.phpt b/ext/curl/tests/curl_postfields_array.phpt index 4fe41eb1e0b5d..47635e78158d1 100644 --- a/ext/curl/tests/curl_postfields_array.phpt +++ b/ext/curl/tests/curl_postfields_array.phpt @@ -38,7 +38,6 @@ $ch = curl_init(); curl_setopt_array($ch, $options); $curl_content = curl_exec($ch); -curl_close($ch); $conn = stream_socket_accept($socket); echo stream_get_contents($conn); diff --git a/ext/curl/tests/curl_pushfunction.phpt b/ext/curl/tests/curl_pushfunction.phpt index 3b43dee4e25c6..c5d88e8dcd0a1 100644 --- a/ext/curl/tests/curl_pushfunction.phpt +++ b/ext/curl/tests/curl_pushfunction.phpt @@ -44,7 +44,6 @@ do { if ($handle !== null) { $responses[] = curl_multi_getcontent($info['handle']); curl_multi_remove_handle($mh, $handle); - curl_close($handle); } } } while ($info); diff --git a/ext/curl/tests/curl_pushfunction_trampoline.phpt b/ext/curl/tests/curl_pushfunction_trampoline.phpt index 55eda0de1065a..a4d85b3819bd7 100644 --- a/ext/curl/tests/curl_pushfunction_trampoline.phpt +++ b/ext/curl/tests/curl_pushfunction_trampoline.phpt @@ -48,7 +48,6 @@ do { if ($handle !== null) { $responses[] = curl_multi_getcontent($info['handle']); curl_multi_remove_handle($mh, $handle); - curl_close($handle); } } } while ($info); diff --git a/ext/curl/tests/curl_read_callback.phpt b/ext/curl/tests/curl_read_callback.phpt index 1319876ec5f2c..f6df70fe91d17 100644 --- a/ext/curl/tests/curl_read_callback.phpt +++ b/ext/curl/tests/curl_read_callback.phpt @@ -31,7 +31,6 @@ curl_setopt($oCurl, CURLOPT_UPLOAD, 1); curl_setopt($oCurl, CURLOPT_READFUNCTION, "custom_readfunction" ); curl_setopt($oCurl, CURLOPT_INFILE, $hReadHandle ); curl_exec($oCurl); -curl_close($oCurl); fclose ($hReadHandle); diff --git a/ext/curl/tests/curl_read_trampoline.phpt b/ext/curl/tests/curl_read_trampoline.phpt index f69caebf79875..38250db2805a9 100644 --- a/ext/curl/tests/curl_read_trampoline.phpt +++ b/ext/curl/tests/curl_read_trampoline.phpt @@ -28,7 +28,6 @@ curl_setopt($oCurl, CURLOPT_UPLOAD, 1); curl_setopt($oCurl, CURLOPT_READFUNCTION, $callback); curl_setopt($oCurl, CURLOPT_INFILE, $hReadHandle ); curl_exec($oCurl); -curl_close($oCurl); fclose ($hReadHandle); diff --git a/ext/curl/tests/curl_reset.phpt b/ext/curl/tests/curl_reset.phpt index 1a0ecfda3b768..80b883a35c436 100644 --- a/ext/curl/tests/curl_reset.phpt +++ b/ext/curl/tests/curl_reset.phpt @@ -23,8 +23,6 @@ curl_reset($ch); curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file); curl_exec($ch); -curl_close($ch); - fclose($testfile_fp); echo file_get_contents($test_file); diff --git a/ext/curl/tests/curl_setopt_CURLOPT_ACCEPT_ENCODING.phpt b/ext/curl/tests/curl_setopt_CURLOPT_ACCEPT_ENCODING.phpt index c170308c2e981..a1983a2270349 100644 --- a/ext/curl/tests/curl_setopt_CURLOPT_ACCEPT_ENCODING.phpt +++ b/ext/curl/tests/curl_setopt_CURLOPT_ACCEPT_ENCODING.phpt @@ -24,8 +24,6 @@ echo curl_getinfo($ch, CURLINFO_HEADER_OUT); curl_setopt($ch, CURLOPT_ACCEPT_ENCODING, NULL); curl_exec($ch); echo curl_getinfo($ch, CURLINFO_HEADER_OUT); - -curl_close($ch); ?> --EXPECTF-- GET /get.inc?test= HTTP/1.1 diff --git a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt index 31661e2eaffb9..85af9b5319e9c 100644 --- a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt +++ b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION.phpt @@ -21,7 +21,6 @@ foreach ([ curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); var_dump(curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $follow)); var_dump(curl_exec($ch)); - curl_close($ch); } ?> --EXPECTF-- diff --git a/ext/curl/tests/curl_setopt_CURLOPT_SSL_SIGNATURE_ALGORITHMS.phpt b/ext/curl/tests/curl_setopt_CURLOPT_SSL_SIGNATURE_ALGORITHMS.phpt new file mode 100644 index 0000000000000..73b4abc85bd4d --- /dev/null +++ b/ext/curl/tests/curl_setopt_CURLOPT_SSL_SIGNATURE_ALGORITHMS.phpt @@ -0,0 +1,40 @@ +--TEST-- +Curl option CURLOPT_SSL_SIGNATURE_ALGORITHMS +--EXTENSIONS-- +curl +--SKIPIF-- += 8.14.0"); + +include 'skipif-nocaddy.inc'; +?> +--FILE-- + +--EXPECT-- +string(4) "pong" +bool(true) +bool(false) +string(52) "failed setting signature algorithms: 'invalid-value'" +bool(true) +string(4) "pong" +bool(true) +string(4) "pong" diff --git a/ext/curl/tests/curl_setopt_array_basic.phpt b/ext/curl/tests/curl_setopt_array_basic.phpt index 361bb35f68127..eb6f547029f17 100644 --- a/ext/curl/tests/curl_setopt_array_basic.phpt +++ b/ext/curl/tests/curl_setopt_array_basic.phpt @@ -43,7 +43,6 @@ ob_start(); // start output buffering curl_setopt_array($ch, $options); $returnContent = curl_exec($ch); -curl_close($ch); var_dump($returnContent); isset($tempname) and is_file($tempname) and @unlink($tempname); diff --git a/ext/curl/tests/curl_setopt_basic002.phpt b/ext/curl/tests/curl_setopt_basic002.phpt index faf7fef6e93e4..e5303438c07f6 100644 --- a/ext/curl/tests/curl_setopt_basic002.phpt +++ b/ext/curl/tests/curl_setopt_basic002.phpt @@ -41,9 +41,6 @@ fclose($handle); unset($handle); var_dump(preg_replace('/[\r\n]/', ' ', file_get_contents($temp_file))); @unlink($temp_file); - -curl_close($ch); - ?> --EXPECTF-- *** Testing curl_setopt with CURLOPT_STDERR diff --git a/ext/curl/tests/curl_setopt_basic003.phpt b/ext/curl/tests/curl_setopt_basic003.phpt index ad56e1e1f24e1..008162c9b4742 100644 --- a/ext/curl/tests/curl_setopt_basic003.phpt +++ b/ext/curl/tests/curl_setopt_basic003.phpt @@ -24,7 +24,7 @@ try { } $curl_content = curl_exec($ch); -curl_close($ch); +$ch = null; var_dump( $curl_content ); @@ -36,7 +36,7 @@ curl_setopt($ch, CURLOPT_URL, $host); $curl_content = curl_exec($ch); ob_end_clean(); -curl_close($ch); +$ch = null; var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_setopt_basic004.phpt b/ext/curl/tests/curl_setopt_basic004.phpt index a54ec157aa065..2ce7d9feb0333 100644 --- a/ext/curl/tests/curl_setopt_basic004.phpt +++ b/ext/curl/tests/curl_setopt_basic004.phpt @@ -21,7 +21,7 @@ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); $curl_content = curl_exec($ch); -curl_close($ch); +$ch = null; var_dump( $curl_content ); @@ -34,7 +34,7 @@ curl_setopt($ch, CURLOPT_URL, $url); ob_start(); $curl_content = curl_exec($ch); ob_end_clean(); -curl_close($ch); +$ch = null; var_dump( $curl_content ); ?> diff --git a/ext/curl/tests/curl_setopt_ssl.phpt b/ext/curl/tests/curl_setopt_ssl.phpt index 3f345930f6244..21d9943fe6032 100644 --- a/ext/curl/tests/curl_setopt_ssl.phpt +++ b/ext/curl/tests/curl_setopt_ssl.phpt @@ -82,7 +82,7 @@ try { $response = curl_exec($ch); check_response($response, $clientCertSubject); check_error($ch); - curl_close($ch); + $ch = null; echo "\n"; echo "case 2: empty client cert and key from string\n"; @@ -96,7 +96,7 @@ try { $response = curl_exec($ch); check_response($response, $clientCertSubject); check_error($ch); - curl_close($ch); + $ch = null; echo "\n"; echo "case 3: client cert and empty key from string\n"; @@ -110,7 +110,7 @@ try { $response = curl_exec($ch); check_response($response, $clientCertSubject); check_error($ch); - curl_close($ch); + $ch = null; echo "\n"; echo "case 4: client cert and key from file\n"; @@ -124,7 +124,7 @@ try { $response = curl_exec($ch); check_response($response, $clientCertSubject); check_error($ch); - curl_close($ch); + $ch = null; echo "\n"; echo "case 5: issuer cert from file\n"; @@ -140,7 +140,7 @@ try { $response = curl_exec($ch); check_response($response, $clientCertSubject); check_error($ch); - curl_close($ch); + $ch = null; echo "\n"; echo "case 6: issuer cert from string\n"; @@ -156,7 +156,7 @@ try { $response = curl_exec($ch); check_response($response, $clientCertSubject); check_error($ch); - curl_close($ch); + $ch = null; echo "\n"; echo "case 7: empty issuer cert from string\n"; @@ -172,7 +172,7 @@ try { $response = curl_exec($ch); check_response($response, $clientCertSubject); check_error($ch); - curl_close($ch); + $ch = null; } finally { // clean up server process diff --git a/ext/curl/tests/curl_share_close_basic001.phpt b/ext/curl/tests/curl_share_close_basic001.phpt index a9c14b5ead55a..9e1827445a0a8 100644 --- a/ext/curl/tests/curl_share_close_basic001.phpt +++ b/ext/curl/tests/curl_share_close_basic001.phpt @@ -13,8 +13,10 @@ curl_share_close($sh); var_dump($sh); ?> ---EXPECT-- +--EXPECTF-- object(CurlShareHandle)#1 (0) { } + +Deprecated: Function curl_share_close() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d object(CurlShareHandle)#1 (0) { } diff --git a/ext/curl/tests/curl_ssh_hostkey_trampoline.phpt b/ext/curl/tests/curl_ssh_hostkey_trampoline.phpt index 84ce8eb85115a..45dd2a6b27683 100644 --- a/ext/curl/tests/curl_ssh_hostkey_trampoline.phpt +++ b/ext/curl/tests/curl_ssh_hostkey_trampoline.phpt @@ -33,8 +33,6 @@ var_dump($host); curl_setopt($ch, CURLOPT_URL, $url); var_dump(curl_setopt($ch, CURLOPT_SSH_HOSTKEYFUNCTION, $callback)); curl_exec($ch); -curl_close($ch); - ?> --EXPECT-- Trampoline for trampoline diff --git a/ext/curl/tests/curl_upkeep_001.phpt b/ext/curl/tests/curl_upkeep_001.phpt index f0680e5cbbfab..77ce4d77130e2 100644 --- a/ext/curl/tests/curl_upkeep_001.phpt +++ b/ext/curl/tests/curl_upkeep_001.phpt @@ -22,7 +22,6 @@ if (curl_exec($ch)) { usleep(300); var_dump(curl_upkeep($ch)); } -curl_close($ch); ?> --EXPECT-- bool(true) diff --git a/ext/curl/tests/curl_write_callback.phpt b/ext/curl/tests/curl_write_callback.phpt index 63f1a3da54a4f..308ee98bb0907 100644 --- a/ext/curl/tests/curl_write_callback.phpt +++ b/ext/curl/tests/curl_write_callback.phpt @@ -26,7 +26,6 @@ $ch = curl_init(); curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'curl_callback'); curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file); curl_exec($ch); -curl_close($ch); // cleanup unlink($log_file); diff --git a/ext/curl/tests/curl_write_file.phpt b/ext/curl/tests/curl_write_file.phpt index b5610222ba18e..eba648c0c5f7d 100644 --- a/ext/curl/tests/curl_write_file.phpt +++ b/ext/curl/tests/curl_write_file.phpt @@ -23,7 +23,6 @@ $ch = curl_init(); curl_setopt($ch, CURLOPT_FILE, $testfile_fp); curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file); curl_exec($ch); -curl_close($ch); fclose($testfile_fp); diff --git a/ext/curl/tests/curl_write_return.phpt b/ext/curl/tests/curl_write_return.phpt index 4f0269c2f1e16..bb6c9364bde8b 100644 --- a/ext/curl/tests/curl_write_return.phpt +++ b/ext/curl/tests/curl_write_return.phpt @@ -21,7 +21,6 @@ $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file); $result = curl_exec($ch); -curl_close($ch); echo $result; diff --git a/ext/curl/tests/curl_write_stdout.phpt b/ext/curl/tests/curl_write_stdout.phpt index b3a2e43516f1c..a23f78eb807cc 100644 --- a/ext/curl/tests/curl_write_stdout.phpt +++ b/ext/curl/tests/curl_write_stdout.phpt @@ -20,7 +20,6 @@ $ch = curl_init(); curl_setopt($ch, CURLOPT_FILE, STDOUT); curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file); curl_exec($ch); -curl_close($ch); // cleanup unlink($log_file); diff --git a/ext/curl/tests/curl_write_trampoline.phpt b/ext/curl/tests/curl_write_trampoline.phpt index 8d604bc7bd4fc..292cec051091f 100644 --- a/ext/curl/tests/curl_write_trampoline.phpt +++ b/ext/curl/tests/curl_write_trampoline.phpt @@ -24,7 +24,6 @@ $ch = curl_init(); curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback); curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file); curl_exec($ch); -curl_close($ch); ?> --CLEAN-- diff --git a/ext/curl/tests/curl_writeheader_callback.phpt b/ext/curl/tests/curl_writeheader_callback.phpt index 3b9b10d02f2ad..e0994c1d023d8 100644 --- a/ext/curl/tests/curl_writeheader_callback.phpt +++ b/ext/curl/tests/curl_writeheader_callback.phpt @@ -24,8 +24,6 @@ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'curl_header_callback'); curl_setopt($ch, CURLOPT_URL, $host); curl_exec($ch); -curl_close($ch); - ?> --EXPECTF-- HTTP/1.1 %d %s diff --git a/ext/curl/tests/skipif-nocaddy.inc b/ext/curl/tests/skipif-nocaddy.inc index ae5442ff28ede..98ffe2a988811 100644 --- a/ext/curl/tests/skipif-nocaddy.inc +++ b/ext/curl/tests/skipif-nocaddy.inc @@ -6,8 +6,6 @@ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $body = curl_exec($ch); -curl_close($ch); - if ($body !== "Caddy is up and running") { die("skip test needs Caddy"); } diff --git a/ext/date/config0.m4 b/ext/date/config0.m4 index 9091803edfa45..c78fcb78e15eb 100644 --- a/ext/date/config0.m4 +++ b/ext/date/config0.m4 @@ -5,16 +5,14 @@ dnl Check for strtoll, atoll AC_CHECK_FUNCS([strtoll atoll]) AX_CHECK_COMPILE_FLAG([-Wno-implicit-fallthrough], - [PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -Wno-implicit-fallthrough"],, - [-Werror]) + [PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -Wno-implicit-fallthrough"]) PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -DHAVE_TIMELIB_CONFIG_H=1" PHP_TIMELIB_CFLAGS="$PHP_DATE_CFLAGS" PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -I@ext_builddir@/lib -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" AX_CHECK_COMPILE_FLAG([-fwrapv], - [PHP_TIMELIB_CFLAGS="$PHP_TIMELIB_CFLAGS -fwrapv"],, - [-Werror]) + [PHP_TIMELIB_CFLAGS="$PHP_TIMELIB_CFLAGS -fwrapv"]) timelib_sources="lib/astro.c lib/dow.c lib/parse_date.c lib/parse_tz.c lib/parse_posix.c lib/timelib.c lib/tm2unixtime.c lib/unixtime2tm.c lib/parse_iso_intervals.c lib/interval.c" diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c index ea1602ef13b4e..1fb7fb15ec01a 100644 --- a/ext/date/lib/parse_date.c +++ b/ext/date/lib/parse_date.c @@ -1,4 +1,4 @@ -/* Generated by re2c 1.0.3 on Wed Sep 11 17:29:29 2024 */ +/* Generated by re2c 1.0.3 on Mon Sep 15 10:40:13 2025 */ #line 1 "ext/date/lib/parse_date.re" /* * The MIT License (MIT) @@ -941,10 +941,12 @@ timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int { timelib_tzinfo *res; timelib_long retval = 0; + size_t paren_count = 0; *tz_not_found = 0; while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') { + paren_count += **ptr == '('; ++*ptr; } if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) { @@ -993,8 +995,9 @@ timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int *tz_not_found = (found == 0); retval = offset; } - while (**ptr == ')') { + while (paren_count > 0 && **ptr == ')') { ++*ptr; + paren_count--; } return retval; } @@ -1018,11 +1021,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) std: s->tok = cursor; s->len = 0; -#line 1151 "ext/date/lib/parse_date.re" +#line 1154 "ext/date/lib/parse_date.re" -#line 1026 "" +#line 1029 "ext/date/lib/parse_date.c" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1203,23 +1206,23 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(2, *YYCURSOR); ++YYCURSOR; YYDEBUG(3, *YYCURSOR); -#line 1984 "ext/date/lib/parse_date.re" +#line 1987 "ext/date/lib/parse_date.re" { s->pos = cursor; s->line++; goto std; } -#line 1212 "" +#line 1215 "ext/date/lib/parse_date.c" yy4: YYDEBUG(4, *YYCURSOR); ++YYCURSOR; yy5: YYDEBUG(5, *YYCURSOR); -#line 1990 "ext/date/lib/parse_date.re" +#line 1993 "ext/date/lib/parse_date.re" { add_error(s, TIMELIB_ERR_UNEXPECTED_CHARACTER, "Unexpected character"); goto std; } -#line 1223 "" +#line 1226 "ext/date/lib/parse_date.c" yy6: YYDEBUG(6, *YYCURSOR); yyaccept = 0; @@ -1234,11 +1237,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy58; yy8: YYDEBUG(8, *YYCURSOR); -#line 1979 "ext/date/lib/parse_date.re" +#line 1982 "ext/date/lib/parse_date.re" { goto std; } -#line 1242 "" +#line 1245 "ext/date/lib/parse_date.c" yy9: YYDEBUG(9, *YYCURSOR); yych = *++YYCURSOR; @@ -1272,11 +1275,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(11, *YYCURSOR); ++YYCURSOR; YYDEBUG(12, *YYCURSOR); -#line 1974 "ext/date/lib/parse_date.re" +#line 1977 "ext/date/lib/parse_date.re" { goto std; } -#line 1280 "" +#line 1283 "ext/date/lib/parse_date.c" yy13: YYDEBUG(13, *YYCURSOR); yyaccept = 1; @@ -1777,7 +1780,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy20: YYDEBUG(20, *YYCURSOR); -#line 1889 "ext/date/lib/parse_date.re" +#line 1892 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("tzcorrection | tz"); @@ -1791,7 +1794,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIMEZONE; } -#line 1795 "" +#line 1798 "ext/date/lib/parse_date.c" yy21: YYDEBUG(21, *YYCURSOR); yych = *++YYCURSOR; @@ -3596,7 +3599,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy81: YYDEBUG(81, *YYCURSOR); -#line 1636 "ext/date/lib/parse_date.re" +#line 1639 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenoyearrev"); TIMELIB_INIT; @@ -3607,7 +3610,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 3611 "" +#line 3614 "ext/date/lib/parse_date.c" yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; @@ -4122,7 +4125,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } if (yych == '.') goto yy289; YYDEBUG(114, *YYCURSOR); -#line 1211 "ext/date/lib/parse_date.re" +#line 1214 "ext/date/lib/parse_date.re" { timelib_ull i; @@ -4147,7 +4150,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 4151 "" +#line 4154 "ext/date/lib/parse_date.c" yy115: YYDEBUG(115, *YYCURSOR); ++YYCURSOR; @@ -5873,7 +5876,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy177: YYDEBUG(177, *YYCURSOR); -#line 1377 "ext/date/lib/parse_date.re" +#line 1380 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("timetiny24 | timeshort24 | timelong24 | iso8601long"); @@ -5900,7 +5903,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 5904 "" +#line 5907 "ext/date/lib/parse_date.c" yy178: YYDEBUG(178, *YYCURSOR); yyaccept = 4; @@ -6929,7 +6932,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy224: YYDEBUG(224, *YYCURSOR); -#line 1471 "ext/date/lib/parse_date.re" +#line 1474 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("americanshort | american"); @@ -6944,7 +6947,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AMERICAN; } -#line 6948 "" +#line 6951 "ext/date/lib/parse_date.c" yy225: YYDEBUG(225, *YYCURSOR); yyaccept = 5; @@ -7187,7 +7190,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy431; yy251: YYDEBUG(251, *YYCURSOR); -#line 1553 "ext/date/lib/parse_date.re" +#line 1556 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datefull"); @@ -7201,7 +7204,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL; } -#line 7205 "" +#line 7208 "ext/date/lib/parse_date.c" yy252: YYDEBUG(252, *YYCURSOR); yyaccept = 3; @@ -7315,7 +7318,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == 'e') goto yy440; yy260: YYDEBUG(260, *YYCURSOR); -#line 1958 "ext/date/lib/parse_date.re" +#line 1961 "ext/date/lib/parse_date.re" { timelib_ull i; DEBUG_OUTPUT("relative"); @@ -7330,7 +7333,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7334 "" +#line 7337 "ext/date/lib/parse_date.c" yy261: YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; @@ -7776,7 +7779,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy471; yy290: YYDEBUG(290, *YYCURSOR); -#line 1237 "ext/date/lib/parse_date.re" +#line 1240 "ext/date/lib/parse_date.re" { timelib_sll i; timelib_ull us; @@ -7815,7 +7818,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7819 "" +#line 7822 "ext/date/lib/parse_date.c" yy291: YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; @@ -7840,7 +7843,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy293: YYDEBUG(293, *YYCURSOR); -#line 1799 "ext/date/lib/parse_date.re" +#line 1802 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("ago"); TIMELIB_INIT; @@ -7860,7 +7863,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AGO; } -#line 7864 "" +#line 7867 "ext/date/lib/parse_date.c" yy294: YYDEBUG(294, *YYCURSOR); yyaccept = 7; @@ -7899,7 +7902,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy295: YYDEBUG(295, *YYCURSOR); -#line 1879 "ext/date/lib/parse_date.re" +#line 1882 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("monthtext"); TIMELIB_INIT; @@ -7908,7 +7911,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 7912 "" +#line 7915 "ext/date/lib/parse_date.c" yy296: YYDEBUG(296, *YYCURSOR); yyaccept = 7; @@ -8483,7 +8486,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy315: YYDEBUG(315, *YYCURSOR); -#line 1820 "ext/date/lib/parse_date.re" +#line 1823 "ext/date/lib/parse_date.re" { const timelib_relunit* relunit; DEBUG_OUTPUT("daytext"); @@ -8500,7 +8503,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEKDAY; } -#line 8504 "" +#line 8507 "ext/date/lib/parse_date.c" yy316: YYDEBUG(316, *YYCURSOR); yych = *++YYCURSOR; @@ -8768,7 +8771,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy325: YYDEBUG(325, *YYCURSOR); -#line 1622 "ext/date/lib/parse_date.re" +#line 1625 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datetextual | datenoyear"); @@ -8781,7 +8784,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 8785 "" +#line 8788 "ext/date/lib/parse_date.c" yy326: YYDEBUG(326, *YYCURSOR); yyaccept = 10; @@ -9475,7 +9478,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy351: YYDEBUG(351, *YYCURSOR); -#line 1168 "ext/date/lib/parse_date.re" +#line 1171 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("now"); TIMELIB_INIT; @@ -9483,7 +9486,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 9487 "" +#line 9490 "ext/date/lib/parse_date.c" yy352: YYDEBUG(352, *YYCURSOR); yyaccept = 2; @@ -10986,7 +10989,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy420: YYDEBUG(420, *YYCURSOR); -#line 1405 "ext/date/lib/parse_date.re" +#line 1408 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("gnunocolon"); TIMELIB_INIT; @@ -11008,7 +11011,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_GNU_NOCOLON; } -#line 11012 "" +#line 11015 "ext/date/lib/parse_date.c" yy421: YYDEBUG(421, *YYCURSOR); yyaccept = 13; @@ -11089,7 +11092,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy422: YYDEBUG(422, *YYCURSOR); -#line 1790 "ext/date/lib/parse_date.re" +#line 1793 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("year4"); TIMELIB_INIT; @@ -11097,7 +11100,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 11101 "" +#line 11104 "ext/date/lib/parse_date.c" yy423: YYDEBUG(423, *YYCURSOR); yyaccept = 3; @@ -11704,7 +11707,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(456, *YYCURSOR); ++YYCURSOR; YYDEBUG(457, *YYCURSOR); -#line 1339 "ext/date/lib/parse_date.re" +#line 1342 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12"); TIMELIB_INIT; @@ -11721,7 +11724,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME12; } -#line 11725 "" +#line 11728 "ext/date/lib/parse_date.c" yy458: YYDEBUG(458, *YYCURSOR); yych = *++YYCURSOR; @@ -13048,7 +13051,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy526: YYDEBUG(526, *YYCURSOR); -#line 1177 "ext/date/lib/parse_date.re" +#line 1180 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("noon"); TIMELIB_INIT; @@ -13059,7 +13062,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 13063 "" +#line 13066 "ext/date/lib/parse_date.c" yy527: YYDEBUG(527, *YYCURSOR); yyaccept = 2; @@ -14105,7 +14108,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy567: YYDEBUG(567, *YYCURSOR); -#line 1539 "ext/date/lib/parse_date.re" +#line 1542 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshort"); @@ -14118,7 +14121,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 14122 "" +#line 14125 "ext/date/lib/parse_date.c" yy568: YYDEBUG(568, *YYCURSOR); yyaccept = 15; @@ -14569,7 +14572,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy600: YYDEBUG(600, *YYCURSOR); -#line 1608 "ext/date/lib/parse_date.re" +#line 1611 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenodayrev"); @@ -14582,7 +14585,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 14586 "" +#line 14589 "ext/date/lib/parse_date.c" yy601: YYDEBUG(601, *YYCURSOR); yych = *++YYCURSOR; @@ -15957,7 +15960,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(696, *YYCURSOR); ++YYCURSOR; YYDEBUG(697, *YYCURSOR); -#line 1594 "ext/date/lib/parse_date.re" +#line 1597 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenoday"); @@ -15970,7 +15973,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 15974 "" +#line 15977 "ext/date/lib/parse_date.c" yy698: YYDEBUG(698, *YYCURSOR); yych = *++YYCURSOR; @@ -16531,7 +16534,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy722: YYDEBUG(722, *YYCURSOR); -#line 1189 "ext/date/lib/parse_date.re" +#line 1192 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("midnight | today"); TIMELIB_INIT; @@ -16540,7 +16543,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 16544 "" +#line 16547 "ext/date/lib/parse_date.c" yy723: YYDEBUG(723, *YYCURSOR); yych = *++YYCURSOR; @@ -16850,7 +16853,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy897; yy739: YYDEBUG(739, *YYCURSOR); -#line 1580 "ext/date/lib/parse_date.re" +#line 1583 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pointed date YY"); @@ -16863,7 +16866,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 16867 "" +#line 16870 "ext/date/lib/parse_date.c" yy740: YYDEBUG(740, *YYCURSOR); yyaccept = 15; @@ -16975,7 +16978,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy752: YYDEBUG(752, *YYCURSOR); -#line 1525 "ext/date/lib/parse_date.re" +#line 1528 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshorter"); @@ -16988,7 +16991,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 16992 "" +#line 16995 "ext/date/lib/parse_date.c" yy753: YYDEBUG(753, *YYCURSOR); yyaccept = 18; @@ -17237,7 +17240,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy777: YYDEBUG(777, *YYCURSOR); -#line 1451 "ext/date/lib/parse_date.re" +#line 1454 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("iso8601nocolon"); @@ -17256,7 +17259,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_NOCOLON; } -#line 17260 "" +#line 17263 "ext/date/lib/parse_date.c" yy778: YYDEBUG(778, *YYCURSOR); yyaccept = 19; @@ -18484,7 +18487,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy849: YYDEBUG(849, *YYCURSOR); -#line 1928 "ext/date/lib/parse_date.re" +#line 1931 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz"); @@ -18513,7 +18516,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 18517 "" +#line 18520 "ext/date/lib/parse_date.c" yy850: YYDEBUG(850, *YYCURSOR); yyaccept = 20; @@ -19557,7 +19560,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy926: YYDEBUG(926, *YYCURSOR); -#line 1686 "ext/date/lib/parse_date.re" +#line 1689 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgydotd"); @@ -19570,7 +19573,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_YEARDAY; } -#line 19574 "" +#line 19577 "ext/date/lib/parse_date.c" yy927: YYDEBUG(927, *YYCURSOR); yyaccept = 21; @@ -19824,7 +19827,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '7') goto yy1059; yy942: YYDEBUG(942, *YYCURSOR); -#line 1719 "ext/date/lib/parse_date.re" +#line 1722 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweek"); @@ -19842,7 +19845,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 19846 "" +#line 19849 "ext/date/lib/parse_date.c" yy943: YYDEBUG(943, *YYCURSOR); yych = *++YYCURSOR; @@ -20318,7 +20321,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == 'e') goto yy1094; yy982: YYDEBUG(982, *YYCURSOR); -#line 1862 "ext/date/lib/parse_date.re" +#line 1865 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -20334,7 +20337,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 20338 "" +#line 20341 "ext/date/lib/parse_date.c" yy983: YYDEBUG(983, *YYCURSOR); yych = *++YYCURSOR; @@ -20681,7 +20684,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1020, *YYCURSOR); ++YYCURSOR; YYDEBUG(1021, *YYCURSOR); -#line 1568 "ext/date/lib/parse_date.re" +#line 1571 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("pointed date YYYY"); TIMELIB_INIT; @@ -20692,7 +20695,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 20696 "" +#line 20699 "ext/date/lib/parse_date.c" yy1022: YYDEBUG(1022, *YYCURSOR); ++YYCURSOR; @@ -20721,7 +20724,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1025: YYDEBUG(1025, *YYCURSOR); -#line 1499 "ext/date/lib/parse_date.re" +#line 1502 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("iso8601date2"); @@ -20734,7 +20737,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20738 "" +#line 20741 "ext/date/lib/parse_date.c" yy1026: YYDEBUG(1026, *YYCURSOR); yyaccept = 15; @@ -20954,7 +20957,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1043: YYDEBUG(1043, *YYCURSOR); -#line 1487 "ext/date/lib/parse_date.re" +#line 1490 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash"); TIMELIB_INIT; @@ -20965,7 +20968,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20969 "" +#line 20972 "ext/date/lib/parse_date.c" yy1044: YYDEBUG(1044, *YYCURSOR); yyaccept = 26; @@ -21080,7 +21083,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1048: YYDEBUG(1048, *YYCURSOR); -#line 1648 "ext/date/lib/parse_date.re" +#line 1651 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenocolon"); TIMELIB_INIT; @@ -21091,7 +21094,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NOCOLON; } -#line 21095 "" +#line 21098 "ext/date/lib/parse_date.c" yy1049: YYDEBUG(1049, *YYCURSOR); yych = *++YYCURSOR; @@ -21161,7 +21164,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1059, *YYCURSOR); ++YYCURSOR; YYDEBUG(1060, *YYCURSOR); -#line 1700 "ext/date/lib/parse_date.re" +#line 1703 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweekday"); @@ -21179,7 +21182,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 21183 "" +#line 21186 "ext/date/lib/parse_date.c" yy1061: YYDEBUG(1061, *YYCURSOR); yych = *++YYCURSOR; @@ -21242,7 +21245,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy1143; yy1070: YYDEBUG(1070, *YYCURSOR); -#line 1738 "ext/date/lib/parse_date.re" +#line 1741 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextshort"); @@ -21255,7 +21258,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 21259 "" +#line 21262 "ext/date/lib/parse_date.c" yy1071: YYDEBUG(1071, *YYCURSOR); yych = *++YYCURSOR; @@ -21728,7 +21731,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++YYCURSOR; yy1107: YYDEBUG(1107, *YYCURSOR); -#line 1199 "ext/date/lib/parse_date.re" +#line 1202 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("tomorrow"); TIMELIB_INIT; @@ -21739,7 +21742,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 21743 "" +#line 21746 "ext/date/lib/parse_date.c" yy1108: YYDEBUG(1108, *YYCURSOR); yyaccept = 28; @@ -22076,7 +22079,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1140, *YYCURSOR); ++YYCURSOR; YYDEBUG(1141, *YYCURSOR); -#line 1752 "ext/date/lib/parse_date.re" +#line 1755 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextreverse"); @@ -22089,7 +22092,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 22093 "" +#line 22096 "ext/date/lib/parse_date.c" yy1142: YYDEBUG(1142, *YYCURSOR); ++YYCURSOR; @@ -22133,7 +22136,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1145: YYDEBUG(1145, *YYCURSOR); -#line 1294 "ext/date/lib/parse_date.re" +#line 1297 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("backof | frontof"); TIMELIB_INIT; @@ -22155,7 +22158,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 22159 "" +#line 22162 "ext/date/lib/parse_date.c" yy1146: YYDEBUG(1146, *YYCURSOR); yyaccept = 29; @@ -22479,7 +22482,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1172: YYDEBUG(1172, *YYCURSOR); -#line 1838 "ext/date/lib/parse_date.re" +#line 1841 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -22502,7 +22505,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22506 "" +#line 22509 "ext/date/lib/parse_date.c" yy1173: YYDEBUG(1173, *YYCURSOR); yych = *++YYCURSOR; @@ -22514,7 +22517,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++YYCURSOR; yy1175: YYDEBUG(1175, *YYCURSOR); -#line 1156 "ext/date/lib/parse_date.re" +#line 1159 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("yesterday"); TIMELIB_INIT; @@ -22525,7 +22528,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22529 "" +#line 22532 "ext/date/lib/parse_date.c" yy1176: YYDEBUG(1176, *YYCURSOR); yyaccept = 31; @@ -23018,7 +23021,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1222, *YYCURSOR); ++YYCURSOR; YYDEBUG(1223, *YYCURSOR); -#line 1904 "ext/date/lib/parse_date.re" +#line 1907 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12"); TIMELIB_INIT; @@ -23041,7 +23044,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 23045 "" +#line 23048 "ext/date/lib/parse_date.c" yy1224: YYDEBUG(1224, *YYCURSOR); yych = *++YYCURSOR; @@ -23543,7 +23546,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1268, *YYCURSOR); ++YYCURSOR; YYDEBUG(1269, *YYCURSOR); -#line 1317 "ext/date/lib/parse_date.re" +#line 1320 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -23564,7 +23567,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEK_DAY_OF_MONTH; } -#line 23568 "" +#line 23571 "ext/date/lib/parse_date.c" yy1270: YYDEBUG(1270, *YYCURSOR); yyaccept = 24; @@ -23611,7 +23614,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1273, *YYCURSOR); ++YYCURSOR; YYDEBUG(1274, *YYCURSOR); -#line 1277 "ext/date/lib/parse_date.re" +#line 1280 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("firstdayof | lastdayof"); TIMELIB_INIT; @@ -23627,12 +23630,12 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 23631 "" +#line 23634 "ext/date/lib/parse_date.c" yy1275: YYDEBUG(1275, *YYCURSOR); ++YYCURSOR; YYDEBUG(1276, *YYCURSOR); -#line 1513 "ext/date/lib/parse_date.re" +#line 1516 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601datex"); TIMELIB_INIT; @@ -23643,7 +23646,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 23647 "" +#line 23650 "ext/date/lib/parse_date.c" yy1277: YYDEBUG(1277, *YYCURSOR); yych = *++YYCURSOR; @@ -23746,7 +23749,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1290, *YYCURSOR); ++YYCURSOR; YYDEBUG(1291, *YYCURSOR); -#line 1357 "ext/date/lib/parse_date.re" +#line 1360 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("mssqltime"); TIMELIB_INIT; @@ -23765,7 +23768,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 23769 "" +#line 23772 "ext/date/lib/parse_date.c" yy1292: YYDEBUG(1292, *YYCURSOR); yych = *++YYCURSOR; @@ -24189,7 +24192,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy1331; yy1329: YYDEBUG(1329, *YYCURSOR); -#line 1660 "ext/date/lib/parse_date.re" +#line 1663 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif"); @@ -24214,7 +24217,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_XMLRPC_SOAP; } -#line 24218 "" +#line 24221 "ext/date/lib/parse_date.c" yy1330: YYDEBUG(1330, *YYCURSOR); yych = *++YYCURSOR; @@ -24584,7 +24587,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= ':') goto yy1383; yy1375: YYDEBUG(1375, *YYCURSOR); -#line 1766 "ext/date/lib/parse_date.re" +#line 1769 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("clf"); @@ -24607,7 +24610,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 24611 "" +#line 24614 "ext/date/lib/parse_date.c" yy1376: YYDEBUG(1376, *YYCURSOR); yyaccept = 33; @@ -24839,7 +24842,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == ':') goto yy1286; goto yy1329; } -#line 1994 "ext/date/lib/parse_date.re" +#line 1997 "ext/date/lib/parse_date.re" } diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index d32be9bfe7be7..c40a5c07c9aa1 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -939,10 +939,12 @@ timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int { timelib_tzinfo *res; timelib_long retval = 0; + size_t paren_count = 0; *tz_not_found = 0; while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') { + paren_count += **ptr == '('; ++*ptr; } if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) { @@ -991,8 +993,9 @@ timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int *tz_not_found = (found == 0); retval = offset; } - while (**ptr == ')') { + while (paren_count > 0 && **ptr == ')') { ++*ptr; + paren_count--; } return retval; } diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c index cdc329431ec45..1fc0ede9679c7 100644 --- a/ext/date/lib/parse_iso_intervals.c +++ b/ext/date/lib/parse_iso_intervals.c @@ -1,4 +1,4 @@ -/* Generated by re2c 1.0.3 on Wed Sep 11 17:29:40 2024 */ +/* Generated by re2c 1.0.3 on Mon Sep 15 10:40:09 2025 */ #line 1 "ext/date/lib/parse_iso_intervals.re" /* * The MIT License (MIT) @@ -180,7 +180,7 @@ static int scan(Scanner *s) -#line 184 "" +#line 184 "ext/date/lib/parse_iso_intervals.c" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -252,7 +252,7 @@ static int scan(Scanner *s) s->pos = cursor; s->line++; goto std; } -#line 256 "" +#line 256 "ext/date/lib/parse_iso_intervals.c" yy4: YYDEBUG(4, *YYCURSOR); ++YYCURSOR; @@ -263,7 +263,7 @@ static int scan(Scanner *s) add_error(s, "Unexpected character"); goto std; } -#line 267 "" +#line 267 "ext/date/lib/parse_iso_intervals.c" yy6: YYDEBUG(6, *YYCURSOR); ++YYCURSOR; @@ -272,7 +272,7 @@ static int scan(Scanner *s) { goto std; } -#line 276 "" +#line 276 "ext/date/lib/parse_iso_intervals.c" yy8: YYDEBUG(8, *YYCURSOR); yyaccept = 0; @@ -330,7 +330,7 @@ static int scan(Scanner *s) TIMELIB_DEINIT; return TIMELIB_PERIOD; } -#line 334 "" +#line 334 "ext/date/lib/parse_iso_intervals.c" yy11: YYDEBUG(11, *YYCURSOR); yych = *++YYCURSOR; @@ -399,7 +399,7 @@ static int scan(Scanner *s) s->have_recurrences = 1; return TIMELIB_PERIOD; } -#line 403 "" +#line 403 "ext/date/lib/parse_iso_intervals.c" yy19: YYDEBUG(19, *YYCURSOR); yych = *++YYCURSOR; @@ -917,7 +917,7 @@ static int scan(Scanner *s) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 921 "" +#line 921 "ext/date/lib/parse_iso_intervals.c" yy91: YYDEBUG(91, *YYCURSOR); yych = *++YYCURSOR; @@ -956,7 +956,7 @@ static int scan(Scanner *s) TIMELIB_DEINIT; return TIMELIB_PERIOD; } -#line 960 "" +#line 960 "ext/date/lib/parse_iso_intervals.c" } #line 321 "ext/date/lib/parse_iso_intervals.re" diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index a2c976af7ed9c..ef57a7ee783f0 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2024 Derick Rethans + * Copyright (c) 2015-2025 Derick Rethans * Copyright (c) 2018,2021 MongoDB, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -30,9 +30,9 @@ # include "timelib_config.h" #endif -#define TIMELIB_VERSION 202212 -#define TIMELIB_EXTENDED_VERSION 20221201 -#define TIMELIB_ASCII_VERSION "2022.12" +#define TIMELIB_VERSION 202214 +#define TIMELIB_EXTENDED_VERSION 20221401 +#define TIMELIB_ASCII_VERSION "2022.14" #include #include diff --git a/ext/date/php_date.c b/ext/date/php_date.c index ae7f62fb8f734..e69512cedb440 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -3968,48 +3968,38 @@ PHP_FUNCTION(date_diff) } /* }}} */ -static bool timezone_initialize(php_timezone_obj *tzobj, const char *tz, size_t tz_len, char **warning_message) /* {{{ */ +static bool timezone_initialize(php_timezone_obj *tzobj, const zend_string *tz_zstr, char **warning_message) /* {{{ */ { - timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time)); + timelib_time dummy_t = {0}; int dst, not_found; - const char *orig_tz = tz; + const char *tz = ZSTR_VAL(tz_zstr); - if (strlen(tz) != tz_len) { - if (warning_message) { - spprintf(warning_message, 0, "Timezone must not contain null bytes"); - } - efree(dummy_t); - return false; - } + ZEND_ASSERT(!zend_str_has_nul_byte(tz_zstr) && "timezone should have been checked to not have null bytes"); - dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, ¬_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); - if ((dummy_t->z >= (100 * 60 * 60)) || (dummy_t->z <= (-100 * 60 * 60))) { + dummy_t.z = timelib_parse_zone(&tz, &dst, &dummy_t, ¬_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); + if ((dummy_t.z >= (100 * 60 * 60)) || (dummy_t.z <= (-100 * 60 * 60))) { if (warning_message) { - spprintf(warning_message, 0, "Timezone offset is out of range (%s)", orig_tz); + spprintf(warning_message, 0, "Timezone offset is out of range (%s)", ZSTR_VAL(tz_zstr)); } - timelib_free(dummy_t->tz_abbr); - efree(dummy_t); + timelib_free(dummy_t.tz_abbr); return false; } - dummy_t->dst = dst; + dummy_t.dst = dst; if (!not_found && (*tz != '\0')) { if (warning_message) { - spprintf(warning_message, 0, "Unknown or bad timezone (%s)", orig_tz); + spprintf(warning_message, 0, "Unknown or bad timezone (%s)", ZSTR_VAL(tz_zstr)); } - timelib_free(dummy_t->tz_abbr); - efree(dummy_t); + timelib_free(dummy_t.tz_abbr); return false; } if (not_found) { if (warning_message) { - spprintf(warning_message, 0, "Unknown or bad timezone (%s)", orig_tz); + spprintf(warning_message, 0, "Unknown or bad timezone (%s)", ZSTR_VAL(tz_zstr)); } - efree(dummy_t); return false; } else { - set_timezone_from_timelib_time(tzobj, dummy_t); - timelib_free(dummy_t->tz_abbr); - efree(dummy_t); + set_timezone_from_timelib_time(tzobj, &dummy_t); + timelib_free(dummy_t.tz_abbr); return true; } } /* }}} */ @@ -4026,7 +4016,7 @@ PHP_FUNCTION(timezone_open) ZEND_PARSE_PARAMETERS_END(); tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value)); - if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz), &warning_message)) { + if (!timezone_initialize(tzobj, tz, &warning_message)) { php_error_docref(NULL, E_WARNING, "%s", warning_message); efree(warning_message); zval_ptr_dtor(return_value); @@ -4047,7 +4037,7 @@ PHP_METHOD(DateTimeZone, __construct) ZEND_PARSE_PARAMETERS_END(); tzobj = Z_PHPTIMEZONE_P(ZEND_THIS); - if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz), &exception_message)) { + if (!timezone_initialize(tzobj, tz, &exception_message)) { zend_throw_exception_ex(date_ce_date_invalid_timezone_exception, 0, "DateTimeZone::__construct(): %s", exception_message); efree(exception_message); RETURN_THROWS(); @@ -4078,7 +4068,10 @@ static bool php_date_timezone_initialize_from_hash(zval **return_value, php_time if (Z_TYPE_P(z_timezone) != IS_STRING) { return false; } - return timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone), NULL); + if (UNEXPECTED(zend_str_has_nul_byte(Z_STR_P(z_timezone)))) { + return false; + } + return timezone_initialize(*tzobj, Z_STR_P(z_timezone), NULL); } /* }}} */ /* {{{ */ @@ -5500,7 +5493,7 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, bool calc_s t->zone_type = TIMELIB_ZONETYPE_ID; if (gmt_offset_is_null) { - gmt_offset = timelib_get_current_offset(t) / 3600; + gmt_offset = timelib_get_current_offset(t) / 3600.0; } timelib_unixtime2local(t, time); diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index 7f60be40b1bc8..0b151c9d42163 100644 --- a/ext/date/php_date.stub.php +++ b/ext/date/php_date.stub.php @@ -3,73 +3,62 @@ /** @generate-class-entries */ /** - * @var string * @cvalue DATE_FORMAT_RFC3339 */ const DATE_ATOM = "Y-m-d\\TH:i:sP"; /** - * @var string * @cvalue DATE_FORMAT_COOKIE */ const DATE_COOKIE = "l, d-M-Y H:i:s T"; /** - * @var string * @cvalue DATE_FORMAT_ISO8601 */ const DATE_ISO8601 = "Y-m-d\\TH:i:sO"; /** - * @var string * @cvalue DATE_FORMAT_ISO8601_EXPANDED */ const DATE_ISO8601_EXPANDED = "X-m-d\\TH:i:sP"; /** - * @var string * @cvalue DATE_FORMAT_RFC822 */ const DATE_RFC822 = "D, d M y H:i:s O"; /** - * @var string * @cvalue DATE_FORMAT_RFC850 */ const DATE_RFC850 = "l, d-M-y H:i:s T"; /** - * @var string * @cvalue DATE_FORMAT_RFC1036 */ const DATE_RFC1036 = "D, d M y H:i:s O"; /** - * @var string * @cvalue DATE_FORMAT_RFC1123 */ const DATE_RFC1123 = "D, d M Y H:i:s O"; /** - * @var string * @cvalue DATE_FORMAT_RFC7231 */ +#[\Deprecated(since: '8.5', message: "as this format ignores the associated timezone and always uses GMT")] const DATE_RFC7231 = "D, d M Y H:i:s \\G\\M\\T"; /** - * @var string * @cvalue DATE_FORMAT_RFC2822 */ const DATE_RFC2822 = "D, d M Y H:i:s O"; /** - * @var string * @cvalue DATE_FORMAT_RFC3339 */ const DATE_RFC3339 = "Y-m-d\\TH:i:sP"; /** - * @var string * @cvalue DATE_FORMAT_RFC3339_EXTENDED */ const DATE_RFC3339_EXTENDED = "Y-m-d\\TH:i:s.vP"; @@ -83,22 +72,22 @@ /** * @var int * @cvalue SUNFUNCS_RET_TIMESTAMP - * @deprecated */ +#[\Deprecated(since: '8.4', message: 'as date_sunrise() and date_sunset() were deprecated in 8.1')] const SUNFUNCS_RET_TIMESTAMP = UNKNOWN; /** * @var int * @cvalue SUNFUNCS_RET_STRING - * @deprecated */ +#[\Deprecated(since: '8.4', message: 'as date_sunrise() and date_sunset() were deprecated in 8.1')] const SUNFUNCS_RET_STRING = UNKNOWN; /** * @var int * @cvalue SUNFUNCS_RET_DOUBLE - * @deprecated */ +#[\Deprecated(since: '8.4', message: 'as date_sunrise() and date_sunset() were deprecated in 8.1')] const SUNFUNCS_RET_DOUBLE = UNKNOWN; function strtotime(string $datetime, ?int $baseTimestamp = null): int|false {} @@ -287,7 +276,6 @@ function date_sun_info(int $timestamp, float $latitude, float $longitude): array interface DateTimeInterface { - public const string ATOM = DATE_ATOM; public const string COOKIE = DATE_COOKIE; @@ -304,6 +292,7 @@ interface DateTimeInterface public const string RFC1123 = DATE_RFC1123; + #[\Deprecated(since: '8.5', message: "as this format ignores the associated timezone and always uses GMT")] public const string RFC7231 = DATE_RFC7231; public const string RFC2822 = DATE_RFC2822; diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index 2a0fd6e5ac009..5b583772e6582 100644 --- a/ext/date/php_date_arginfo.h +++ b/ext/date/php_date_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 4e61617ca7c877aa3811d674d47850f23157074b */ + * Stub hash: 16d118b58a713bbea5174c170129aa9f6206de68 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0) @@ -798,7 +798,7 @@ static void register_php_date_symbols(int module_number) ZEND_ASSERT(strcmp(DATE_FORMAT_RFC1036, "D, d M y H:i:s O") == 0); REGISTER_STRING_CONSTANT("DATE_RFC1123", DATE_FORMAT_RFC1123, CONST_PERSISTENT); ZEND_ASSERT(strcmp(DATE_FORMAT_RFC1123, "D, d M Y H:i:s O") == 0); - REGISTER_STRING_CONSTANT("DATE_RFC7231", DATE_FORMAT_RFC7231, CONST_PERSISTENT); + zend_constant *const_DATE_RFC7231 = REGISTER_STRING_CONSTANT("DATE_RFC7231", DATE_FORMAT_RFC7231, CONST_PERSISTENT | CONST_DEPRECATED); ZEND_ASSERT(strcmp(DATE_FORMAT_RFC7231, "D, d M Y H:i:s \\G\\M\\T") == 0); REGISTER_STRING_CONSTANT("DATE_RFC2822", DATE_FORMAT_RFC2822, CONST_PERSISTENT); ZEND_ASSERT(strcmp(DATE_FORMAT_RFC2822, "D, d M Y H:i:s O") == 0); @@ -808,58 +808,62 @@ static void register_php_date_symbols(int module_number) ZEND_ASSERT(strcmp(DATE_FORMAT_RFC3339_EXTENDED, "Y-m-d\\TH:i:s.vP") == 0); REGISTER_STRING_CONSTANT("DATE_RSS", DATE_FORMAT_RFC1123, CONST_PERSISTENT); REGISTER_STRING_CONSTANT("DATE_W3C", DATE_FORMAT_RFC3339, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SUNFUNCS_RET_TIMESTAMP", SUNFUNCS_RET_TIMESTAMP, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("SUNFUNCS_RET_STRING", SUNFUNCS_RET_STRING, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("SUNFUNCS_RET_DOUBLE", SUNFUNCS_RET_DOUBLE, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_SUNFUNCS_RET_TIMESTAMP = REGISTER_LONG_CONSTANT("SUNFUNCS_RET_TIMESTAMP", SUNFUNCS_RET_TIMESTAMP, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_SUNFUNCS_RET_STRING = REGISTER_LONG_CONSTANT("SUNFUNCS_RET_STRING", SUNFUNCS_RET_STRING, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_SUNFUNCS_RET_DOUBLE = REGISTER_LONG_CONSTANT("SUNFUNCS_RET_DOUBLE", SUNFUNCS_RET_DOUBLE, CONST_PERSISTENT | CONST_DEPRECATED); zend_attribute *attribute_Deprecated_func_strftime_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "strftime", sizeof("strftime") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_strftime_0_arg0; - zend_string *attribute_Deprecated_func_strftime_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_strftime_0_arg0, attribute_Deprecated_func_strftime_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_strftime_0->args[0].value, &attribute_Deprecated_func_strftime_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_strftime_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_strftime_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_strftime_0_arg1; zend_string *attribute_Deprecated_func_strftime_0_arg1_str = zend_string_init("use IntlDateFormatter::format() instead", strlen("use IntlDateFormatter::format() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_strftime_0_arg1, attribute_Deprecated_func_strftime_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_strftime_0->args[1].value, &attribute_Deprecated_func_strftime_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_strftime_0->args[1].value, attribute_Deprecated_func_strftime_0_arg1_str); attribute_Deprecated_func_strftime_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_gmstrftime_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "gmstrftime", sizeof("gmstrftime") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_gmstrftime_0_arg0; - zend_string *attribute_Deprecated_func_gmstrftime_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_gmstrftime_0_arg0, attribute_Deprecated_func_gmstrftime_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_gmstrftime_0->args[0].value, &attribute_Deprecated_func_gmstrftime_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_gmstrftime_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_gmstrftime_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_gmstrftime_0_arg1; - zend_string *attribute_Deprecated_func_gmstrftime_0_arg1_str = zend_string_init("use IntlDateFormatter::format() instead", strlen("use IntlDateFormatter::format() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_gmstrftime_0_arg1, attribute_Deprecated_func_gmstrftime_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_gmstrftime_0->args[1].value, &attribute_Deprecated_func_gmstrftime_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_gmstrftime_0->args[1].value, attribute_Deprecated_func_strftime_0_arg1_str); attribute_Deprecated_func_gmstrftime_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_date_sunrise_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "date_sunrise", sizeof("date_sunrise") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_date_sunrise_0_arg0; - zend_string *attribute_Deprecated_func_date_sunrise_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_date_sunrise_0_arg0, attribute_Deprecated_func_date_sunrise_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_date_sunrise_0->args[0].value, &attribute_Deprecated_func_date_sunrise_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_date_sunrise_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_date_sunrise_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_date_sunrise_0_arg1; zend_string *attribute_Deprecated_func_date_sunrise_0_arg1_str = zend_string_init("use date_sun_info() instead", strlen("use date_sun_info() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_date_sunrise_0_arg1, attribute_Deprecated_func_date_sunrise_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_date_sunrise_0->args[1].value, &attribute_Deprecated_func_date_sunrise_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_date_sunrise_0->args[1].value, attribute_Deprecated_func_date_sunrise_0_arg1_str); attribute_Deprecated_func_date_sunrise_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_date_sunset_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "date_sunset", sizeof("date_sunset") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_date_sunset_0_arg0; - zend_string *attribute_Deprecated_func_date_sunset_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_date_sunset_0_arg0, attribute_Deprecated_func_date_sunset_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_date_sunset_0->args[0].value, &attribute_Deprecated_func_date_sunset_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_date_sunset_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_date_sunset_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_date_sunset_0_arg1; - zend_string *attribute_Deprecated_func_date_sunset_0_arg1_str = zend_string_init("use date_sun_info() instead", strlen("use date_sun_info() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_date_sunset_0_arg1, attribute_Deprecated_func_date_sunset_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_date_sunset_0->args[1].value, &attribute_Deprecated_func_date_sunset_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_date_sunset_0->args[1].value, attribute_Deprecated_func_date_sunrise_0_arg1_str); attribute_Deprecated_func_date_sunset_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_DATE_RFC7231_0 = zend_add_global_constant_attribute(const_DATE_RFC7231, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_DATE_RFC7231_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_DATE_RFC7231_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_DATE_RFC7231_0_arg1_str = zend_string_init("as this format ignores the associated timezone and always uses GMT", strlen("as this format ignores the associated timezone and always uses GMT"), 1); + ZVAL_STR(&attribute_Deprecated_const_DATE_RFC7231_0->args[1].value, attribute_Deprecated_const_DATE_RFC7231_0_arg1_str); + attribute_Deprecated_const_DATE_RFC7231_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0 = zend_add_global_constant_attribute(const_SUNFUNCS_RET_TIMESTAMP, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0_arg1_str = zend_string_init("as date_sunrise() and date_sunset() were deprecated in 8.1", strlen("as date_sunrise() and date_sunset() were deprecated in 8.1"), 1); + ZVAL_STR(&attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0->args[1].value, attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0_arg1_str); + attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_SUNFUNCS_RET_STRING_0 = zend_add_global_constant_attribute(const_SUNFUNCS_RET_STRING, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_SUNFUNCS_RET_STRING_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_SUNFUNCS_RET_STRING_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_SUNFUNCS_RET_STRING_0->args[1].value, attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0_arg1_str); + attribute_Deprecated_const_SUNFUNCS_RET_STRING_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0 = zend_add_global_constant_attribute(const_SUNFUNCS_RET_DOUBLE, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0->args[1].value, attribute_Deprecated_const_SUNFUNCS_RET_TIMESTAMP_0_arg1_str); + attribute_Deprecated_const_SUNFUNCS_RET_DOUBLE_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_DateTimeInterface(void) @@ -929,7 +933,7 @@ static zend_class_entry *register_class_DateTimeInterface(void) zend_string *const_RFC7231_value_str = zend_string_init(DATE_FORMAT_RFC7231, strlen(DATE_FORMAT_RFC7231), 1); ZVAL_STR(&const_RFC7231_value, const_RFC7231_value_str); zend_string *const_RFC7231_name = zend_string_init_interned("RFC7231", sizeof("RFC7231") - 1, 1); - zend_declare_typed_class_constant(class_entry, const_RFC7231_name, &const_RFC7231_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + zend_class_constant *const_RFC7231 = zend_declare_typed_class_constant(class_entry, const_RFC7231_name, &const_RFC7231_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); zend_string_release(const_RFC7231_name); zval const_RFC2822_value; @@ -967,6 +971,14 @@ static zend_class_entry *register_class_DateTimeInterface(void) zend_declare_typed_class_constant(class_entry, const_W3C_name, &const_W3C_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); zend_string_release(const_W3C_name); + + zend_attribute *attribute_Deprecated_const_RFC7231_0 = zend_add_class_constant_attribute(class_entry, const_RFC7231, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_RFC7231_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_RFC7231_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_RFC7231_0_arg1_str = zend_string_init("as this format ignores the associated timezone and always uses GMT", strlen("as this format ignores the associated timezone and always uses GMT"), 1); + ZVAL_STR(&attribute_Deprecated_const_RFC7231_0->args[1].value, attribute_Deprecated_const_RFC7231_0_arg1_str); + attribute_Deprecated_const_RFC7231_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + return class_entry; } @@ -993,82 +1005,64 @@ static zend_class_entry *register_class_DateTimeImmutable(zend_class_entry *clas zend_string *attribute_name_NoDiscard_func_modify_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_modify_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "modify", sizeof("modify") - 1), attribute_name_NoDiscard_func_modify_0, 1); zend_string_release(attribute_name_NoDiscard_func_modify_0); - zval attribute_NoDiscard_func_modify_0_arg0; zend_string *attribute_NoDiscard_func_modify_0_arg0_str = zend_string_init("as DateTimeImmutable::modify() does not modify the object itself", strlen("as DateTimeImmutable::modify() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_modify_0_arg0, attribute_NoDiscard_func_modify_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_modify_0->args[0].value, &attribute_NoDiscard_func_modify_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_modify_0->args[0].value, attribute_NoDiscard_func_modify_0_arg0_str); attribute_NoDiscard_func_modify_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_add_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_add_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "add", sizeof("add") - 1), attribute_name_NoDiscard_func_add_0, 1); zend_string_release(attribute_name_NoDiscard_func_add_0); - zval attribute_NoDiscard_func_add_0_arg0; zend_string *attribute_NoDiscard_func_add_0_arg0_str = zend_string_init("as DateTimeImmutable::add() does not modify the object itself", strlen("as DateTimeImmutable::add() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_add_0_arg0, attribute_NoDiscard_func_add_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_add_0->args[0].value, &attribute_NoDiscard_func_add_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_add_0->args[0].value, attribute_NoDiscard_func_add_0_arg0_str); attribute_NoDiscard_func_add_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_sub_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_sub_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "sub", sizeof("sub") - 1), attribute_name_NoDiscard_func_sub_0, 1); zend_string_release(attribute_name_NoDiscard_func_sub_0); - zval attribute_NoDiscard_func_sub_0_arg0; zend_string *attribute_NoDiscard_func_sub_0_arg0_str = zend_string_init("as DateTimeImmutable::sub() does not modify the object itself", strlen("as DateTimeImmutable::sub() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_sub_0_arg0, attribute_NoDiscard_func_sub_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_sub_0->args[0].value, &attribute_NoDiscard_func_sub_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_sub_0->args[0].value, attribute_NoDiscard_func_sub_0_arg0_str); attribute_NoDiscard_func_sub_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_settimezone_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_settimezone_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "settimezone", sizeof("settimezone") - 1), attribute_name_NoDiscard_func_settimezone_0, 1); zend_string_release(attribute_name_NoDiscard_func_settimezone_0); - zval attribute_NoDiscard_func_settimezone_0_arg0; zend_string *attribute_NoDiscard_func_settimezone_0_arg0_str = zend_string_init("as DateTimeImmutable::setTimezone() does not modify the object itself", strlen("as DateTimeImmutable::setTimezone() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_settimezone_0_arg0, attribute_NoDiscard_func_settimezone_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_settimezone_0->args[0].value, &attribute_NoDiscard_func_settimezone_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_settimezone_0->args[0].value, attribute_NoDiscard_func_settimezone_0_arg0_str); attribute_NoDiscard_func_settimezone_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_settime_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_settime_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "settime", sizeof("settime") - 1), attribute_name_NoDiscard_func_settime_0, 1); zend_string_release(attribute_name_NoDiscard_func_settime_0); - zval attribute_NoDiscard_func_settime_0_arg0; zend_string *attribute_NoDiscard_func_settime_0_arg0_str = zend_string_init("as DateTimeImmutable::setTime() does not modify the object itself", strlen("as DateTimeImmutable::setTime() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_settime_0_arg0, attribute_NoDiscard_func_settime_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_settime_0->args[0].value, &attribute_NoDiscard_func_settime_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_settime_0->args[0].value, attribute_NoDiscard_func_settime_0_arg0_str); attribute_NoDiscard_func_settime_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_setdate_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_setdate_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setdate", sizeof("setdate") - 1), attribute_name_NoDiscard_func_setdate_0, 1); zend_string_release(attribute_name_NoDiscard_func_setdate_0); - zval attribute_NoDiscard_func_setdate_0_arg0; zend_string *attribute_NoDiscard_func_setdate_0_arg0_str = zend_string_init("as DateTimeImmutable::setDate() does not modify the object itself", strlen("as DateTimeImmutable::setDate() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_setdate_0_arg0, attribute_NoDiscard_func_setdate_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_setdate_0->args[0].value, &attribute_NoDiscard_func_setdate_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_setdate_0->args[0].value, attribute_NoDiscard_func_setdate_0_arg0_str); attribute_NoDiscard_func_setdate_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_setisodate_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_setisodate_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setisodate", sizeof("setisodate") - 1), attribute_name_NoDiscard_func_setisodate_0, 1); zend_string_release(attribute_name_NoDiscard_func_setisodate_0); - zval attribute_NoDiscard_func_setisodate_0_arg0; zend_string *attribute_NoDiscard_func_setisodate_0_arg0_str = zend_string_init("as DateTimeImmutable::setISODate() does not modify the object itself", strlen("as DateTimeImmutable::setISODate() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_setisodate_0_arg0, attribute_NoDiscard_func_setisodate_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_setisodate_0->args[0].value, &attribute_NoDiscard_func_setisodate_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_setisodate_0->args[0].value, attribute_NoDiscard_func_setisodate_0_arg0_str); attribute_NoDiscard_func_setisodate_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_settimestamp_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_settimestamp_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "settimestamp", sizeof("settimestamp") - 1), attribute_name_NoDiscard_func_settimestamp_0, 1); zend_string_release(attribute_name_NoDiscard_func_settimestamp_0); - zval attribute_NoDiscard_func_settimestamp_0_arg0; zend_string *attribute_NoDiscard_func_settimestamp_0_arg0_str = zend_string_init("as DateTimeImmutable::setTimestamp() does not modify the object itself", strlen("as DateTimeImmutable::setTimestamp() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_settimestamp_0_arg0, attribute_NoDiscard_func_settimestamp_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_settimestamp_0->args[0].value, &attribute_NoDiscard_func_settimestamp_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_settimestamp_0->args[0].value, attribute_NoDiscard_func_settimestamp_0_arg0_str); attribute_NoDiscard_func_settimestamp_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_setmicrosecond_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_setmicrosecond_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setmicrosecond", sizeof("setmicrosecond") - 1), attribute_name_NoDiscard_func_setmicrosecond_0, 1); zend_string_release(attribute_name_NoDiscard_func_setmicrosecond_0); - zval attribute_NoDiscard_func_setmicrosecond_0_arg0; zend_string *attribute_NoDiscard_func_setmicrosecond_0_arg0_str = zend_string_init("as DateTimeImmutable::setMicrosecond() does not modify the object itself", strlen("as DateTimeImmutable::setMicrosecond() does not modify the object itself"), 1); - ZVAL_STR(&attribute_NoDiscard_func_setmicrosecond_0_arg0, attribute_NoDiscard_func_setmicrosecond_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_setmicrosecond_0->args[0].value, &attribute_NoDiscard_func_setmicrosecond_0_arg0); + ZVAL_STR(&attribute_NoDiscard_func_setmicrosecond_0->args[0].value, attribute_NoDiscard_func_setmicrosecond_0_arg0_str); attribute_NoDiscard_func_setmicrosecond_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); return class_entry; diff --git a/ext/date/tests/DateTimeImmutable_constants.phpt b/ext/date/tests/DateTimeImmutable_constants.phpt index 16de66e89f1e4..c3192231916df 100644 --- a/ext/date/tests/DateTimeImmutable_constants.phpt +++ b/ext/date/tests/DateTimeImmutable_constants.phpt @@ -21,7 +21,10 @@ var_dump( ); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Constant DATE_RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d + +Deprecated: Constant DateTimeInterface::RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d bool(true) bool(true) bool(true) diff --git a/ext/date/tests/DateTimeInterface_constants.phpt b/ext/date/tests/DateTimeInterface_constants.phpt index c740ea4d951b1..d02eddf4d680c 100644 --- a/ext/date/tests/DateTimeInterface_constants.phpt +++ b/ext/date/tests/DateTimeInterface_constants.phpt @@ -21,7 +21,10 @@ var_dump( ); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Constant DATE_RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d + +Deprecated: Constant DateTimeInterface::RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d bool(true) bool(true) bool(true) diff --git a/ext/date/tests/DateTime_constants.phpt b/ext/date/tests/DateTime_constants.phpt index bca573d8f72aa..fada757775c68 100644 --- a/ext/date/tests/DateTime_constants.phpt +++ b/ext/date/tests/DateTime_constants.phpt @@ -21,7 +21,10 @@ var_dump( ); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Constant DATE_RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d + +Deprecated: Constant DateTimeInterface::RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d bool(true) bool(true) bool(true) diff --git a/ext/date/tests/DateTime_format_basic2.phpt b/ext/date/tests/DateTime_format_basic2.phpt index 2946cf2c681f4..a829f9c216376 100644 --- a/ext/date/tests/DateTime_format_basic2.phpt +++ b/ext/date/tests/DateTime_format_basic2.phpt @@ -24,7 +24,7 @@ var_dump($date->format(DateTime::RSS)); var_dump($date->format(DateTime::W3C)); ?> ---EXPECT-- +--EXPECTF-- *** Testing date_format() : basic functionality - formatting constants *** string(25) "2005-07-14T22:30:41+01:00" string(34) "Thursday, 14-Jul-2005 22:30:41 BST" @@ -34,6 +34,8 @@ string(29) "Thu, 14 Jul 05 22:30:41 +0100" string(32) "Thursday, 14-Jul-05 22:30:41 BST" string(29) "Thu, 14 Jul 05 22:30:41 +0100" string(31) "Thu, 14 Jul 2005 22:30:41 +0100" + +Deprecated: Constant DateTimeInterface::RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d string(29) "Thu, 14 Jul 2005 22:30:41 GMT" string(31) "Thu, 14 Jul 2005 22:30:41 +0100" string(25) "2005-07-14T22:30:41+01:00" diff --git a/ext/date/tests/bug33536.phpt b/ext/date/tests/bug33536.phpt index aa5f5ddb38bfe..e41fc7f1e2490 100644 --- a/ext/date/tests/bug33536.phpt +++ b/ext/date/tests/bug33536.phpt @@ -4,10 +4,6 @@ Bug #33456 (strtotime defaults to now even on non time string) --EXPECT-- bool(false) -1970-01-01 -1970-01-01 diff --git a/ext/date/tests/bug44780.phpt b/ext/date/tests/bug44780.phpt index 5c822d48e6add..964c619f9b73f 100644 --- a/ext/date/tests/bug44780.phpt +++ b/ext/date/tests/bug44780.phpt @@ -2,8 +2,8 @@ Bug #44780 (some time zone offsets not recognized by timezone_name_from_abbr) --FILE-- --EXPECT-- string(12) "Asia/Kolkata" diff --git a/ext/date/tests/bug62852_var2.phpt b/ext/date/tests/bug62852_var2.phpt index 4749d2a9bb21f..5e867873a31f2 100644 --- a/ext/date/tests/bug62852_var2.phpt +++ b/ext/date/tests/bug62852_var2.phpt @@ -22,6 +22,8 @@ try { var_dump( $foo ); ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug62852_var2.php:%d Stack trace: #0 [internal function]: DateTime->__unserialize(Array) diff --git a/ext/date/tests/bug62852_var3.phpt b/ext/date/tests/bug62852_var3.phpt index 7049efcebd84f..4130f3142fa62 100644 --- a/ext/date/tests/bug62852_var3.phpt +++ b/ext/date/tests/bug62852_var3.phpt @@ -22,6 +22,8 @@ try { var_dump( $foo ); ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug62852_var3.php:%d Stack trace: #0 [internal function]: DateTime->__unserialize(Array) diff --git a/ext/date/tests/bug74080.phpt b/ext/date/tests/bug74080.phpt deleted file mode 100644 index a86c78144e66e..0000000000000 --- a/ext/date/tests/bug74080.phpt +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -Bug #74080 Provide an RFC7231 date time format ---FILE-- - ---EXPECT-- -string(29) "Sat, 30 Apr 2016 17:52:13 GMT" diff --git a/ext/date/tests/date_constants.phpt b/ext/date/tests/date_constants.phpt index 27d933166555d..2305ddbc31291 100644 --- a/ext/date/tests/date_constants.phpt +++ b/ext/date/tests/date_constants.phpt @@ -44,7 +44,8 @@ Date constants DATE_W3C == DateTime::W3C ); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Constant DATE_RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d string(25) "2006-07-01T14:27:30+02:00" string(25) "2006-05-30T14:32:13+02:00" string(35) "Saturday, 01-Jul-2006 14:27:30 CEST" @@ -74,6 +75,10 @@ string(31) "Tue, 30 May 2006 14:32:13 +0200" string(25) "2006-07-01T14:27:30+02:00" string(25) "2006-05-30T14:32:13+02:00" + +Deprecated: Constant DATE_RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d + +Deprecated: Constant DateTimeInterface::RFC7231 is deprecated since 8.5, as this format ignores the associated timezone and always uses GMT in %s on line %d bool(true) bool(true) bool(true) diff --git a/ext/date/tests/date_sun_info_003.phpt b/ext/date/tests/date_sun_info_003.phpt index 7e74bab621e41..e3cdc93823f2f 100644 --- a/ext/date/tests/date_sun_info_003.phpt +++ b/ext/date/tests/date_sun_info_003.phpt @@ -5,38 +5,43 @@ edgarsandi - --FILE-- $elem ) { - echo "$key: " . date("H:i:s", $elem) . "\n"; + +function print_sun_info(string $date) { + echo $date, "\n"; + $sun_info = date_sun_info(strtotime($date), 89.00, 1.00); + foreach ($sun_info as $key => $elem ) { + echo "$key: " . match ($elem) { + true => 'always', + false => 'never', + default => date("H:i:s", $elem), + } . "\n"; + } } +print_sun_info("2015-01-12 00:00:00 UTC"); echo "\n"; +print_sun_info("2015-09-12 00:00:00 UTC"); -$sun_info = date_sun_info(strtotime("2015-09-12 00:00:00 UTC"), 89.00, 1.00); -foreach ($sun_info as $key => $elem ) { - echo "$key: " . date("H:i:s", $elem) . "\n"; -} - -echo "Done\n"; ?> --EXPECT-- -sunrise: 21:00:00 -sunset: 21:00:00 +2015-01-12 00:00:00 UTC +sunrise: never +sunset: never transit: 10:03:48 -civil_twilight_begin: 21:00:00 -civil_twilight_end: 21:00:00 -nautical_twilight_begin: 21:00:00 -nautical_twilight_end: 21:00:00 -astronomical_twilight_begin: 21:00:00 -astronomical_twilight_end: 21:00:00 +civil_twilight_begin: never +civil_twilight_end: never +nautical_twilight_begin: never +nautical_twilight_end: never +astronomical_twilight_begin: never +astronomical_twilight_end: never -sunrise: 21:00:01 -sunset: 21:00:01 +2015-09-12 00:00:00 UTC +sunrise: always +sunset: always transit: 08:52:44 -civil_twilight_begin: 21:00:01 -civil_twilight_end: 21:00:01 -nautical_twilight_begin: 21:00:01 -nautical_twilight_end: 21:00:01 -astronomical_twilight_begin: 21:00:01 -astronomical_twilight_end: 21:00:01 -Done +civil_twilight_begin: always +civil_twilight_end: always +nautical_twilight_begin: always +nautical_twilight_end: always +astronomical_twilight_begin: always +astronomical_twilight_end: always diff --git a/ext/date/tests/date_sunrise_and_sunset_basic.phpt b/ext/date/tests/date_sunrise_and_sunset_basic.phpt index e5f5efa73e177..d2ed26dea2b6d 100644 --- a/ext/date/tests/date_sunrise_and_sunset_basic.phpt +++ b/ext/date/tests/date_sunrise_and_sunset_basic.phpt @@ -25,12 +25,12 @@ var_dump(gettype(date_sunset(time()))); --EXPECTF-- Basic test for date_sunrise() and date_sunset() -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d %s %s %d %d, sunrise time : %d:%d -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunset() is deprecated since 8.1, use date_sun_info() instead in %s on line %d %s %s %d %d, sunset time : %d:%d diff --git a/ext/date/tests/gh14732.phpt b/ext/date/tests/gh14732.phpt index 63c626963a9d5..19b5f3b481f4b 100644 --- a/ext/date/tests/gh14732.phpt +++ b/ext/date/tests/gh14732.phpt @@ -31,12 +31,12 @@ date_sun_info(): Argument #2 ($latitude) must be finite date_sun_info(): Argument #3 ($longitude) must be finite date_sun_info(): Argument #3 ($longitude) must be finite -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunset() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) diff --git a/ext/date/tests/gh16454.phpt b/ext/date/tests/gh16454.phpt index e3a35a1ba1998..0acad74dce726 100644 --- a/ext/date/tests/gh16454.phpt +++ b/ext/date/tests/gh16454.phpt @@ -8,22 +8,22 @@ var_dump(date_sunset(0, SUNFUNCS_RET_STRING, 61, -150, 90, PHP_FLOAT_MAX)); var_dump(date_sunset(0, SUNFUNCS_RET_STRING, 61, -150, 90, -PHP_FLOAT_MAX)); ?> --EXPECTF-- -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunset() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunset() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) diff --git a/ext/date/tests/gh18481.phpt b/ext/date/tests/gh18481.phpt index 074f244c3a3a3..8c997357e2750 100644 --- a/ext/date/tests/gh18481.phpt +++ b/ext/date/tests/gh18481.phpt @@ -8,22 +8,22 @@ foreach ([-NAN, NAN, INF, -INF] as $offset) { } ?> --EXPECTF-- -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d Deprecated: Function date_sunrise() is deprecated since 8.1, use date_sun_info() instead in %s on line %d bool(false) diff --git a/ext/date/tests/sunfuncts_partial_hour_utc_offset.phpt b/ext/date/tests/sunfuncts_partial_hour_utc_offset.phpt new file mode 100644 index 0000000000000..279e40fa654c3 --- /dev/null +++ b/ext/date/tests/sunfuncts_partial_hour_utc_offset.phpt @@ -0,0 +1,18 @@ +--TEST-- +Incorrect timezone detection in date_sunrise() for partial-hour UTC offsets +--FILE-- +setTimestamp(date_sun_info($timestamp, $longitude, $latitude)['sunrise']); +echo $dt->format('H:i'), "\n"; +?> +--EXPECT-- +06:10 +06:11 diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 086998973e20a..37f05ebb94fe7 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -256,14 +256,14 @@ static void dba_close_info(dba_info *info) if (info->flags & DBA_PERSISTENT) { php_stream_pclose(info->fp); } else { - php_stream_close(info->fp); + php_stream_free(info->fp, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR); } } if (info->lock.fp) { if (info->flags & DBA_PERSISTENT) { php_stream_pclose(info->lock.fp); } else { - php_stream_close(info->lock.fp); + php_stream_free(info->lock.fp, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR); } } @@ -516,6 +516,17 @@ static zend_always_inline zend_string *php_dba_zend_string_dup_safe(zend_string } } +/* See mysqlnd_fixup_regular_list */ +static void php_dba_fixup_regular_list(php_stream *stream) +{ + dtor_func_t origin_dtor = EG(regular_list).pDestructor; + EG(regular_list).pDestructor = NULL; + zend_hash_index_del(&EG(regular_list), stream->res->handle); + EG(regular_list).pDestructor = origin_dtor; + efree(stream->res); + stream->res = NULL; +} + /* {{{ php_dba_open */ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) { @@ -827,6 +838,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) /* do not log errors for .lck file while in read only mode on .lck file */ lock_file_mode = "rb"; connection->info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, NULL); + if (connection->info->lock.fp && !persistent_flag) { + php_dba_fixup_regular_list(connection->info->lock.fp); + } } if (!connection->info->lock.fp) { /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */ @@ -837,6 +851,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) zend_string *opened_path = NULL; connection->info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path); if (connection->info->lock.fp) { + if (!persistent_flag) { + php_dba_fixup_regular_list(connection->info->lock.fp); + } if (is_db_lock) { if (opened_path) { /* replace the path info with the real path of the opened file */ @@ -873,6 +890,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) connection->info->fp = connection->info->lock.fp; /* use the same stream for locking and database access */ } else { connection->info->fp = php_stream_open_wrapper(ZSTR_VAL(connection->info->path), file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL); + if (connection->info->fp && !persistent_flag) { + php_dba_fixup_regular_list(connection->info->fp); + } } if (!connection->info->fp) { /* stream operation already wrote an error message */ diff --git a/ext/dba/dba.stub.php b/ext/dba/dba.stub.php index fbc0be8cdadad..ab9758e2c2bb6 100644 --- a/ext/dba/dba.stub.php +++ b/ext/dba/dba.stub.php @@ -14,7 +14,6 @@ final class Connection namespace { #ifdef DBA_LMDB - /** @var int */ const DBA_LMDB_USE_SUB_DIR = 0; /** * @var int diff --git a/ext/dba/dba_arginfo.h b/ext/dba/dba_arginfo.h index c2befedfda7c7..6274c1dd43956 100644 --- a/ext/dba/dba_arginfo.h +++ b/ext/dba/dba_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: da00cabc7b6930f1b834af8978b38945df96212f */ + * Stub hash: d7ff53b73d3921c41ffd8279ea724bcd3a6d8542 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_dba_popen, 0, 2, Dba\\Connection, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) diff --git a/ext/dba/tests/gh19706.phpt b/ext/dba/tests/gh19706.phpt new file mode 100644 index 0000000000000..4cf3ef5f54d3c --- /dev/null +++ b/ext/dba/tests/gh19706.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-19706 (dba stream resource mismanagement) +--EXTENSIONS-- +dba +--FILE-- + +--CLEAN-- + +--EXPECT-- +object(Dba\Connection)#1 (0) { +} +object(Dba\Connection)#1 (0) { +} diff --git a/ext/dl_test/dl_test.stub.php b/ext/dl_test/dl_test.stub.php index 9c3bbac6b267d..42a30f233f57c 100644 --- a/ext/dl_test/dl_test.stub.php +++ b/ext/dl_test/dl_test.stub.php @@ -5,7 +5,6 @@ * @undocumentable */ -/** @var int */ const DL_TEST_CONST = 42; function dl_test_test1(): void {} diff --git a/ext/dl_test/dl_test_arginfo.h b/ext/dl_test/dl_test_arginfo.h index 1b3b65aa7e677..588d0b1b6e6e1 100644 --- a/ext/dl_test/dl_test_arginfo.h +++ b/ext/dl_test/dl_test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 75bdb57a45060b123fe48003fef43d2af07726e1 */ + * Stub hash: 3c47a0da41b4548eb68c4124bd54cbac22f60c01 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dl_test_test1, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() diff --git a/ext/dom/attr.c b/ext/dom/attr.c index dfe3abc1a885c..5a0900d657eea 100644 --- a/ext/dom/attr.c +++ b/ext/dom/attr.c @@ -201,10 +201,10 @@ PHP_METHOD(DOMAttr, isId) bool dom_compare_value(const xmlAttr *attr, const xmlChar *value) { - bool free; - xmlChar *attr_value = php_libxml_attr_value(attr, &free); + bool should_free; + xmlChar *attr_value = php_libxml_attr_value(attr, &should_free); bool result = xmlStrEqual(attr_value, value); - if (free) { + if (should_free) { xmlFree(attr_value); } return result; diff --git a/ext/dom/document.c b/ext/dom/document.c index 1c447c4cb8272..e281e65ce07c7 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1105,8 +1105,9 @@ static void php_dom_transfer_document_ref(xmlNodePtr node, php_libxml_ref_obj *n } } -/* Workaround for bug that was fixed in https://github.com/GNOME/libxml2/commit/4bc3ebf3eaba352fbbce2ef70ad00a3c7752478a */ -#if LIBXML_VERSION < 21000 +/* Workaround for bug that was fixed in https://github.com/GNOME/libxml2/commit/4bc3ebf3eaba352fbbce2ef70ad00a3c7752478a + * and https://github.com/GNOME/libxml2/commit/bc7ab5a2e61e4b36accf6803c5b0e245c11154b1 */ +#if LIBXML_VERSION < 21300 static xmlChar *libxml_copy_dicted_string(xmlDictPtr src_dict, xmlDictPtr dst_dict, xmlChar *str) { if (str == NULL) { @@ -1123,30 +1124,43 @@ static xmlChar *libxml_copy_dicted_string(xmlDictPtr src_dict, xmlDictPtr dst_di static void libxml_fixup_name_and_content(xmlDocPtr src_doc, xmlDocPtr dst_doc, xmlNodePtr node) { - if (src_doc != NULL && dst_doc != src_doc && src_doc->dict != NULL) { + if (node->type == XML_ENTITY_REF_NODE) { + node->children = NULL; /* Break link with original document. */ + } + if (src_doc != NULL && src_doc->dict != NULL) { + ZEND_ASSERT(dst_doc != src_doc); node->name = libxml_copy_dicted_string(src_doc->dict, dst_doc->dict, BAD_CAST node->name); node->content = libxml_copy_dicted_string(src_doc->dict, NULL, node->content); } } -static void libxml_fixup_name_and_content_element(xmlDocPtr src_doc, xmlDocPtr dst_doc, xmlNodePtr node) +static void libxml_fixup_name_and_content_outer(xmlDocPtr src_doc, xmlDocPtr dst_doc, xmlNodePtr node) { libxml_fixup_name_and_content(src_doc, dst_doc, node); - for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) { - libxml_fixup_name_and_content(src_doc, dst_doc, (xmlNodePtr) attr); + + if (node->type == XML_ELEMENT_NODE) { + for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) { + libxml_fixup_name_and_content(src_doc, dst_doc, (xmlNodePtr) attr); + for (xmlNodePtr attr_child = attr->children; attr_child != NULL; attr_child = attr_child->next) { + libxml_fixup_name_and_content(src_doc, dst_doc, attr_child); + } + } } - for (xmlNodePtr child = node->children; child != NULL; child = child->next) { - libxml_fixup_name_and_content_element(src_doc, dst_doc, child); + if (node->type == XML_ELEMENT_NODE || node->type == XML_ATTRIBUTE_NODE) { + for (xmlNodePtr child = node->children; child != NULL; child = child->next) { + libxml_fixup_name_and_content_outer(src_doc, dst_doc, child); + } } } #endif bool php_dom_adopt_node(xmlNodePtr nodep, dom_object *dom_object_new_document, xmlDocPtr new_document) { - xmlDocPtr original_document = nodep->doc; - php_libxml_invalidate_node_list_cache_from_doc(original_document); - if (nodep->doc != new_document) { + xmlDocPtr old_doc = nodep->doc; + + php_libxml_invalidate_node_list_cache_from_doc(old_doc); + if (old_doc != new_document) { php_libxml_invalidate_node_list_cache(dom_object_new_document->document); /* Note for ATTRIBUTE_NODE: specified is always true in ext/dom, @@ -1156,16 +1170,18 @@ bool php_dom_adopt_node(xmlNodePtr nodep, dom_object *dom_object_new_document, x xmlSetTreeDoc(nodep, new_document); php_dom_libxml_ns_mapper *ns_mapper = php_dom_get_ns_mapper(dom_object_new_document); php_dom_libxml_reconcile_modern(ns_mapper, nodep); -#if LIBXML_VERSION < 21000 - libxml_fixup_name_and_content_element(original_document, new_document, nodep); -#endif } else { - int ret = xmlDOMWrapAdoptNode(NULL, original_document, nodep, new_document, NULL, /* options, unused */ 0); + int ret = xmlDOMWrapAdoptNode(NULL, old_doc, nodep, new_document, NULL, /* options, unused */ 0); if (UNEXPECTED(ret != 0)) { return false; } } +#if LIBXML_VERSION < 21300 + /* Must be first before transferring the ref to ensure the old document dictionary stays alive. */ + libxml_fixup_name_and_content_outer(old_doc, new_document, nodep); +#endif + php_dom_transfer_document_ref(nodep, dom_object_new_document->document); } else { xmlUnlinkNode(nodep); diff --git a/ext/dom/dom_properties.h b/ext/dom/dom_properties.h index f9402c929d937..100c6c3d3e78b 100644 --- a/ext/dom/dom_properties.h +++ b/ext/dom/dom_properties.h @@ -109,6 +109,7 @@ zend_result dom_entity_reference_child_nodes_read(dom_object *obj, zval *retval) zend_result dom_namednodemap_length_read(dom_object *obj, zval *retval); /* parent node properties */ +zend_result dom_parent_node_children_read(dom_object *obj, zval *retval); zend_result dom_parent_node_first_element_child_read(dom_object *obj, zval *retval); zend_result dom_parent_node_last_element_child_read(dom_object *obj, zval *retval); zend_result dom_parent_node_child_element_count(dom_object *obj, zval *retval); diff --git a/ext/dom/element.c b/ext/dom/element.c index 27e2845c9f0cb..dbab931301599 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -62,7 +62,7 @@ PHP_METHOD(DOMElement, __construct) if (uri_len > 0) { errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len); if (errorcode == 0) { - nodep = xmlNewNode (NULL, BAD_CAST localname); + nodep = xmlNewDocNode(NULL, NULL, BAD_CAST localname, NULL); if (nodep != NULL && uri != NULL) { nsptr = dom_get_ns(nodep, uri, &errorcode, prefix); xmlSetNs(nodep, nsptr); @@ -88,7 +88,7 @@ PHP_METHOD(DOMElement, __construct) php_dom_throw_error(NAMESPACE_ERR, true); RETURN_THROWS(); } - nodep = xmlNewNode(NULL, BAD_CAST name); + nodep = xmlNewDocNode(NULL, NULL, BAD_CAST name, NULL); } if (!nodep) { @@ -177,18 +177,21 @@ zend_result dom_element_class_name_write(dom_object *obj, zval *newval) } /* }}} */ -zval *dom_element_class_list_zval(dom_object *obj) +zval *dom_get_prop_checked_offset(dom_object *obj, uint32_t offset, const char *name) { - const uint32_t PROP_INDEX = 0; - #if ZEND_DEBUG - zend_string *class_list_str = ZSTR_INIT_LITERAL("classList", false); - const zend_property_info *prop_info = zend_get_property_info(dom_modern_element_class_entry, class_list_str, 0); - zend_string_release_ex(class_list_str, false); - ZEND_ASSERT(OBJ_PROP_TO_NUM(prop_info->offset) == PROP_INDEX); + zend_string *name_zstr = ZSTR_INIT_LITERAL(name, false); + const zend_property_info *prop_info = zend_get_property_info(obj->std.ce, name_zstr, 0); + zend_string_release_ex(name_zstr, false); + ZEND_ASSERT(OBJ_PROP_TO_NUM(prop_info->offset) == offset); #endif - return OBJ_PROP_NUM(&obj->std, PROP_INDEX); + return OBJ_PROP_NUM(&obj->std, offset); +} + +zval *dom_element_class_list_zval(dom_object *obj) +{ + return dom_get_prop_checked_offset(obj, 1, "classList"); } /* {{{ classList TokenList @@ -839,6 +842,44 @@ PHP_METHOD(Dom_Element, getElementsByTagName) } /* }}} end dom_element_get_elements_by_tag_name */ +PHP_METHOD(Dom_Element, getElementsByClassName) +{ + dom_object *intern, *namednode; + zend_string *class_names; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &class_names) == FAILURE) { + RETURN_THROWS(); + } + + if (ZSTR_LEN(class_names) > INT_MAX) { + zend_argument_value_error(1, "is too long"); + RETURN_THROWS(); + } + + DOM_GET_THIS_INTERN(intern); + + object_init_ex(return_value, dom_html_collection_class_entry); + namednode = Z_DOMOBJ_P(return_value); + + HashTable *token_set; + ALLOC_HASHTABLE(token_set); + zend_hash_init(token_set, 0, NULL, NULL, false); + dom_ordered_set_parser(token_set, ZSTR_VAL(class_names), intern->document->quirks_mode == PHP_LIBXML_QUIRKS); + + if (zend_hash_num_elements(token_set) == 0) { + php_dom_create_obj_map(intern, namednode, NULL, NULL, NULL, &php_dom_obj_map_noop); + + zend_hash_destroy(token_set); + FREE_HASHTABLE(token_set); + } else { + php_dom_create_obj_map(intern, namednode, NULL, NULL, NULL, &php_dom_obj_map_by_class_name); + + dom_nnodemap_object *map = namednode->ptr; + map->array = token_set; + map->release_array = true; + } +} + /* should_free_result must be initialized to false */ static const xmlChar *dom_get_attribute_ns(dom_object *intern, xmlNodePtr elemp, const char *uri, size_t uri_len, const char *name, bool *should_free_result) { diff --git a/ext/dom/html_collection.c b/ext/dom/html_collection.c index e5dca84de75ff..a4e2d6ad6fbed 100644 --- a/ext/dom/html_collection.c +++ b/ext/dom/html_collection.c @@ -46,34 +46,35 @@ static dom_named_item dom_html_collection_named_item(zend_string *key, zend_obje /* 2. Return the first element in the collection for which at least one of the following is true: */ xmlNodePtr basep = dom_object_get_node(objmap->baseobj); - if (basep != NULL) { - zend_long cur = 0; - zend_long next = cur; /* not +1, otherwise we skip the first candidate */ - xmlNodePtr candidate = basep->children; - while (candidate != NULL) { - candidate = dom_get_elements_by_tag_name_ns_raw(basep, candidate, objmap->ns, objmap->local, objmap->local_lower, &cur, next); - if (candidate == NULL) { + if (basep != NULL && basep->children != NULL) { + php_dom_obj_map_collection_iter iter = {0}; + iter.candidate = basep->children; + iter.basep = basep; + + while (true) { + objmap->handler->collection_named_item_iter(objmap, &iter); + if (iter.candidate == NULL) { break; } + ZEND_ASSERT(iter.candidate->type == XML_ELEMENT_NODE); + xmlAttrPtr attr; /* it has an ID which is key; */ - if ((attr = xmlHasNsProp(candidate, BAD_CAST "id", NULL)) != NULL && dom_compare_value(attr, BAD_CAST ZSTR_VAL(key))) { + if ((attr = xmlHasNsProp(iter.candidate, BAD_CAST "id", NULL)) != NULL && dom_compare_value(attr, BAD_CAST ZSTR_VAL(key))) { ret.context_intern = objmap->baseobj; - ret.node = candidate; + ret.node = iter.candidate; return ret; } /* it is in the HTML namespace and has a name attribute whose value is key; */ - else if (php_dom_ns_is_fast(candidate, php_dom_ns_is_html_magic_token)) { - if ((attr = xmlHasNsProp(candidate, BAD_CAST "name", NULL)) != NULL && dom_compare_value(attr, BAD_CAST ZSTR_VAL(key))) { + else if (php_dom_ns_is_fast(iter.candidate, php_dom_ns_is_html_magic_token)) { + if ((attr = xmlHasNsProp(iter.candidate, BAD_CAST "name", NULL)) != NULL && dom_compare_value(attr, BAD_CAST ZSTR_VAL(key))) { ret.context_intern = objmap->baseobj; - ret.node = candidate; + ret.node = iter.candidate; return ret; } } - - next = cur + 1; } } @@ -141,4 +142,23 @@ int dom_html_collection_has_dimension(zend_object *object, zval *member, int che } } +HashTable *dom_html_collection_get_gc(zend_object *object, zval **table, int *n) +{ + dom_nnodemap_object *objmap = php_dom_obj_from_obj(object)->ptr; + + if (objmap->baseobj) { + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + zend_get_gc_buffer_add_obj(gc_buffer, &objmap->baseobj->std); + zend_get_gc_buffer_use(gc_buffer, table, n); + + if (object->properties == NULL && object->ce->default_properties_count == 0) { + return NULL; + } else { + return zend_std_get_properties(object); + } + } else { + return zend_std_get_gc(object, table, n); + } +} + #endif diff --git a/ext/dom/html_collection.h b/ext/dom/html_collection.h index a94daa1aae805..59ab50abc1b05 100644 --- a/ext/dom/html_collection.h +++ b/ext/dom/html_collection.h @@ -19,5 +19,6 @@ zval *dom_html_collection_read_dimension(zend_object *object, zval *offset, int type, zval *rv); int dom_html_collection_has_dimension(zend_object *object, zval *member, int check_empty); +HashTable *dom_html_collection_get_gc(zend_object *object, zval **table, int *n); #endif diff --git a/ext/dom/html_document.c b/ext/dom/html_document.c index 19d7faef0dbb2..954403ca1c5df 100644 --- a/ext/dom/html_document.c +++ b/ext/dom/html_document.c @@ -84,16 +84,7 @@ typedef struct dom_decoding_encoding_ctx { /* https://dom.spec.whatwg.org/#dom-document-implementation */ zend_result dom_modern_document_implementation_read(dom_object *obj, zval *retval) { - const uint32_t PROP_INDEX = 0; - -#if ZEND_DEBUG - zend_string *implementation_str = ZSTR_INIT_LITERAL("implementation", false); - const zend_property_info *prop_info = zend_get_property_info(dom_abstract_base_document_class_entry, implementation_str, 0); - zend_string_release_ex(implementation_str, false); - ZEND_ASSERT(OBJ_PROP_TO_NUM(prop_info->offset) == PROP_INDEX); -#endif - - zval *cached_implementation = OBJ_PROP_NUM(&obj->std, PROP_INDEX); + zval *cached_implementation = dom_get_prop_checked_offset(obj, 1, "implementation"); if (Z_ISUNDEF_P(cached_implementation)) { php_dom_create_implementation(cached_implementation, true); } diff --git a/ext/dom/lexbor/selectors-adapted/selectors.c b/ext/dom/lexbor/selectors-adapted/selectors.c index e5348292f4372..13feb4fc1bf14 100644 --- a/ext/dom/lexbor/selectors-adapted/selectors.c +++ b/ext/dom/lexbor/selectors-adapted/selectors.c @@ -1,9 +1,9 @@ /* - * Copyright (C) 2021-2024 Alexander Borisov + * Copyright (C) 2021-2025 Alexander Borisov * * Author: Alexander Borisov * Adapted for PHP + libxml2 by: Niels Dossche - * Based on Lexbor (upstream commit b347aa4e4da4e82b1cae18989ceea1aa0278daf1) + * Based on Lexbor (upstream commit 971faf11a5f45433b9193a143e2897d8c0fd5611) */ #include @@ -35,11 +35,6 @@ static void dom_lxb_str_wrapper_release(dom_lxb_str_wrapper *wrapper) } } -static zend_always_inline bool lxb_selectors_adapted_is_matchable_child(const xmlNode *node) -{ - return CMP_NODE_TYPE(node, XML_ELEMENT_NODE); -} - static zend_always_inline bool lxb_selectors_adapted_cmp_local_name_literal(const xmlNode *node, const char *name) { return strcmp((const char *) node->name, name) == 0; @@ -181,48 +176,74 @@ static zend_always_inline void lxb_selectors_adapted_set_entry_id(lxb_selectors_ } static lxb_status_t -lxb_selectors_state_tree(lxb_selectors_t *selectors, const xmlNode *root, - const lxb_css_selector_list_t *list); +lxb_selectors_tree(lxb_selectors_t *selectors, const xmlNode *root); static lxb_status_t -lxb_selectors_state_run(lxb_selectors_t *selectors, const xmlNode *node, - const lxb_css_selector_list_t *list); +lxb_selectors_run(lxb_selectors_t *selectors, const xmlNode *node); static lxb_selectors_entry_t * lxb_selectors_state_find(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry); static lxb_selectors_entry_t * -lxb_selectors_state_find_check(lxb_selectors_t *selectors, const xmlNode *node, - const lxb_css_selector_t *selector, - lxb_selectors_entry_t *entry); +lxb_selectors_state_found_check(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +static lxb_selectors_entry_t * +lxb_selectors_state_found_check_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +static lxb_selectors_entry_t * +lxb_selectors_state_found(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +static lxb_selectors_entry_t * +lxb_selectors_state_found_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +static lxb_selectors_entry_t * +lxb_selectors_state_not_found(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + +static lxb_selectors_entry_t * +lxb_selectors_state_not_found_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); static lxb_selectors_entry_t * -lxb_selectors_state_pseudo_class_function(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); +lxb_selectors_next_list(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); -static const xmlNode * -lxb_selectors_next_node(lxb_selectors_nested_t *main); +static lxb_selectors_entry_t * +lxb_selectors_next_list_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); -static const xmlNode * -lxb_selectors_state_has_relative(const xmlNode *node, - const lxb_css_selector_t *selector); +static lxb_selectors_entry_t * +lxb_selectors_make_following(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); static lxb_selectors_entry_t * -lxb_selectors_state_after_find_has(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); +lxb_selectors_make_following_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); static lxb_selectors_entry_t * lxb_selectors_state_after_find(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry); +static lxb_selectors_entry_t * +lxb_selectors_state_after_not(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + static lxb_selectors_entry_t * lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry); +static lxb_selectors_entry_t * +lxb_selectors_state_nth_child_found(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry); + static bool lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, const xmlNode *node); + const xmlNode *node); static bool lxb_selectors_match_element(const lxb_css_selector_t *selector, @@ -244,7 +265,8 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, const xmlNode *node); static bool -lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, +lxb_selectors_pseudo_class_function(lxb_selectors_t *selectors, + const lxb_css_selector_t *selector, const xmlNode *node); static bool @@ -280,6 +302,10 @@ static lxb_status_t lxb_selectors_cb_not(const xmlNode *node, lxb_css_selector_specificity_t spec, void *ctx); +static lxb_status_t +lxb_selectors_cb_nth_ok(const xmlNode *node, + lxb_css_selector_specificity_t spec, void *ctx); + lxb_status_t lxb_selectors_init(lxb_selectors_t *selectors) @@ -319,17 +345,107 @@ lxb_selectors_destroy(lxb_selectors_t *selectors) selectors->nested = lexbor_dobject_destroy(selectors->nested, true); } +static lxb_selectors_entry_t * +lxb_selectors_state_entry_create(lxb_selectors_t *selectors, + const lxb_css_selector_t *selector, + lxb_selectors_entry_t *root, + const xmlNode *node) +{ + lxb_selectors_entry_t *entry; + lxb_css_selector_combinator_t combinator; + + combinator = selector->combinator; + + do { + selector = selector->prev; + + entry = lexbor_dobject_calloc(selectors->objs); + + entry->combinator = selector->combinator; + entry->selector = selector; + entry->node = node; + + if (root->prev != NULL) { + root->prev->next = entry; + entry->prev = root->prev; + } + + entry->next = root; + root->prev = entry; + } + while (selector->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE + && selector->prev != NULL); + + entry->combinator = combinator; + + return entry; +} + +static lxb_selectors_entry_t * +lxb_selectors_state_entry_create_forward(lxb_selectors_t *selectors, + const lxb_css_selector_t *selector, + lxb_selectors_entry_t *root, + const xmlNode *node) +{ + lxb_selectors_entry_t *entry; + + selector = selector->next; + + entry = lexbor_dobject_calloc(selectors->objs); + + entry->combinator = selector->combinator; + entry->selector = selector; + entry->node = node; + + entry->prev = root; + root->next = entry; + + return entry; +} + +static lxb_selectors_entry_t * +lxb_selectors_entry_make_first(lxb_selectors_t *selectors, + lxb_css_selector_t *selector) +{ + lxb_selectors_entry_t *entry, *prev; + + prev = NULL; + + do { + entry = lexbor_dobject_calloc(selectors->objs); + + entry->selector = selector; + entry->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; + + if (prev != NULL) { + prev->next = entry; + entry->prev = prev; + } + + if (selector->combinator != LXB_CSS_SELECTOR_COMBINATOR_CLOSE + || selector->prev == NULL) + { + break; + } + + prev = entry; + selector = selector->prev; + } + while (true); + + return entry; +} + lxb_inline const xmlNode * lxb_selectors_descendant(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, const xmlNode *node) { node = node->parent; while (node != NULL) { if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE) - && lxb_selectors_match(selectors, entry, selector, node)) + && lxb_selectors_match(selectors, entry, node)) { return node; } @@ -340,11 +456,69 @@ lxb_selectors_descendant(lxb_selectors_t *selectors, return NULL; } +lxb_inline const xmlNode * +lxb_selectors_descendant_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry, + const xmlNode *node) +{ + const xmlNode *root; + lxb_selectors_nested_t *current = selectors->current; + + if (entry->prev != NULL) { + root = entry->prev->node; + } + else { + root = current->root; + } + + do { + if (node->children != NULL) { + node = node->children; + } + else { + + next: + + while (node != root && node->next == NULL) { + node = node->parent; + } + + if (node == root) { + break; + } + + node = node->next; + } + + if (!CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { + goto next; + } + + if (lxb_selectors_match(selectors, entry, node)) { + return node; + } + } + while (node != NULL); + + return NULL; +} + lxb_inline const xmlNode * lxb_selectors_close(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, const xmlNode *node) + const xmlNode *node) +{ + if (lxb_selectors_match(selectors, entry, node)) { + return node; + } + + return NULL; +} + +lxb_inline const xmlNode * +lxb_selectors_close_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry, const xmlNode *node) { - if (lxb_selectors_match(selectors, entry, selector, node)) { + if (lxb_selectors_match(selectors, entry, node)) { return node; } @@ -353,12 +527,12 @@ lxb_selectors_close(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, lxb_inline const xmlNode * lxb_selectors_child(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, const xmlNode *root) + const xmlNode *root) { root = root->parent; if (root != NULL && CMP_NODE_TYPE(root, XML_ELEMENT_NODE) - && lxb_selectors_match(selectors, entry, selector, root)) + && lxb_selectors_match(selectors, entry, root)) { return root; } @@ -366,15 +540,47 @@ lxb_selectors_child(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, return NULL; } +lxb_inline const xmlNode * +lxb_selectors_child_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry, const xmlNode *root) +{ + if (entry->prev != NULL) { + if (entry->prev->node == root) { + root = root->children; + } + else { + root = root->next; + } + } + else if (selectors->current->root == root) { + root = root->children; + } + else { + root = root->next; + } + + while (root != NULL) { + if (CMP_NODE_TYPE(root, XML_ELEMENT_NODE) + && lxb_selectors_match(selectors, entry, root)) + { + return root; + } + + root = root->next; + } + + return NULL; +} + lxb_inline const xmlNode * lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, const xmlNode *node) + const xmlNode *node) { node = node->prev; while (node != NULL) { if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { - if (lxb_selectors_match(selectors, entry, selector, node)) { + if (lxb_selectors_match(selectors, entry, node)) { return node; } @@ -387,15 +593,36 @@ lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, return NULL; } +lxb_inline const xmlNode * +lxb_selectors_sibling_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry, const xmlNode *node) +{ + node = node->next; + + while (node != NULL) { + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { + if (lxb_selectors_match(selectors, entry, node)) { + return node; + } + + return NULL; + } + + node = node->next; + } + + return NULL; +} + lxb_inline const xmlNode * lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, const xmlNode *node) + const xmlNode *node) { node = node->prev; while (node != NULL) { if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE) && - lxb_selectors_match(selectors, entry, selector, node)) + lxb_selectors_match(selectors, entry, node)) { return node; } @@ -406,26 +633,72 @@ lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry return NULL; } +lxb_inline const xmlNode * +lxb_selectors_following_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry, + const xmlNode *node) +{ + node = node->next; + + while (node != NULL) { + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE) && + lxb_selectors_match(selectors, entry, node)) + { + return node; + } + + node = node->next; + } + + return NULL; +} + +lxb_inline void +lxb_selectors_switch_to_found_check(lxb_selectors_t *selectors, + lxb_selectors_nested_t *current) +{ + if (current->forward) { + selectors->state = lxb_selectors_state_found_check_forward; + } + else { + selectors->state = lxb_selectors_state_found_check; + } +} + +lxb_inline void +lxb_selectors_switch_to_not_found(lxb_selectors_t *selectors, + lxb_selectors_nested_t *current) +{ + if (current->forward) { + selectors->state = lxb_selectors_state_not_found_forward; + } + else { + selectors->state = lxb_selectors_state_not_found; + } +} + lxb_status_t lxb_selectors_find(lxb_selectors_t *selectors, const xmlNode *root, const lxb_css_selector_list_t *list, lxb_selectors_cb_f cb, void *ctx) { - lxb_selectors_entry_t entry = {0}; + lxb_selectors_entry_t *entry; lxb_selectors_nested_t nested; - entry.combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - entry.selector = list->last; + entry = lxb_selectors_entry_make_first(selectors, list->last); nested.parent = NULL; - nested.entry = &entry; + nested.entry = entry; + nested.first = entry; + nested.top = entry; nested.cb = cb; nested.ctx = ctx; + nested.forward = false; selectors->current = &nested; selectors->status = LXB_STATUS_OK; - return lxb_selectors_state_tree(selectors, root, list); + return lxb_selectors_tree(selectors, root); } lxb_status_t @@ -434,35 +707,43 @@ lxb_selectors_match_node(lxb_selectors_t *selectors, const xmlNode *node, lxb_selectors_cb_f cb, void *ctx) { lxb_status_t status; + lxb_selectors_entry_t *entry; lxb_selectors_nested_t nested; if (!CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { return LXB_STATUS_OK; } - lxb_selectors_entry_t entry = {0}; - - entry.combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - entry.selector = list->last; + entry = lxb_selectors_entry_make_first(selectors, list->last); nested.parent = NULL; - nested.entry = &entry; + nested.entry = entry; + nested.first = entry; + nested.top = entry; nested.cb = cb; nested.ctx = ctx; + nested.forward = false; selectors->current = &nested; selectors->status = LXB_STATUS_OK; - status = lxb_selectors_state_run(selectors, node, list); + status = lxb_selectors_run(selectors, node); lxb_selectors_clean(selectors); return status; } +lxb_status_t +lxb_selectors_find_reverse(lxb_selectors_t *selectors, const xmlNode *root, + const lxb_css_selector_list_t *list, + lxb_selectors_cb_f cb, void *ctx) +{ + return lxb_selectors_find(selectors, root, list, cb, ctx); +} + static lxb_status_t -lxb_selectors_state_tree(lxb_selectors_t *selectors, const xmlNode *root, - const lxb_css_selector_list_t *list) +lxb_selectors_tree(lxb_selectors_t *selectors, const xmlNode *root) { lxb_status_t status; const xmlNode *node; @@ -491,7 +772,7 @@ lxb_selectors_state_tree(lxb_selectors_t *selectors, const xmlNode *root, goto next; } - status = lxb_selectors_state_run(selectors, node, list); + status = lxb_selectors_run(selectors, node); if (status != LXB_STATUS_OK) { if (status == LXB_STATUS_STOP) { break; @@ -529,32 +810,24 @@ lxb_selectors_state_tree(lxb_selectors_t *selectors, const xmlNode *root, } static lxb_status_t -lxb_selectors_state_run(lxb_selectors_t *selectors, const xmlNode *node, - const lxb_css_selector_list_t *list) +lxb_selectors_run(lxb_selectors_t *selectors, const xmlNode *node) { lxb_selectors_entry_t *entry; + lxb_selectors_nested_t *current = selectors->current; - entry = selectors->current->entry; + entry = current->entry; entry->node = node; + current->root = node; selectors->state = lxb_selectors_state_find; - selectors->first = entry; - -again: do { entry = selectors->state(selectors, entry); } while (entry != NULL); - if (selectors->current->parent != NULL - && selectors->status == LXB_STATUS_OK) - { - entry = selectors->current->entry; - selectors->state = selectors->current->return_state; - - goto again; - } + current->first = current->top; + current->entry = current->top; return selectors->status; } @@ -564,84 +837,28 @@ lxb_selectors_state_find(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry) { const xmlNode *node; - lxb_selectors_entry_t *next; - const lxb_css_selector_t *selector; - const lxb_css_selector_anb_of_t *anb; - const lxb_css_selector_pseudo_t *pseudo; - - selector = entry->selector; - - if (selector->type == LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS_FUNCTION) { - pseudo = &selector->u.pseudo; - - /* Optimizing. */ - - switch (pseudo->type) { - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD: - anb = pseudo->data; - - if (anb->of != NULL) { - break; - } - - goto godoit; - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE: - goto godoit; - - default: - break; - } - - if (entry->nested == NULL) { - next = lexbor_dobject_calloc(selectors->objs); - - next->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - - entry->nested = lexbor_dobject_calloc(selectors->nested); - - entry->nested->entry = next; - entry->nested->parent = selectors->current; - } - - selectors->state = lxb_selectors_state_pseudo_class_function; - selectors->current->last = entry; - selectors->current = entry->nested; - - next = entry->nested->entry; - next->node = entry->node; - - return next; - } - -godoit: + selectors->state = lxb_selectors_state_found_check; switch (entry->combinator) { case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - node = lxb_selectors_descendant(selectors, entry, - selector, entry->node); + node = lxb_selectors_descendant(selectors, entry, entry->node); break; case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - node = lxb_selectors_close(selectors, entry, - selector, entry->node); + node = lxb_selectors_close(selectors, entry, entry->node); break; case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - node = lxb_selectors_child(selectors, entry, - selector, entry->node); + node = lxb_selectors_child(selectors, entry, entry->node); break; case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - node = lxb_selectors_sibling(selectors, entry, - selector, entry->node); + node = lxb_selectors_sibling(selectors, entry, entry->node); break; case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = lxb_selectors_following(selectors, entry, - selector, entry->node); + node = lxb_selectors_following(selectors, entry, entry->node); break; case LXB_CSS_SELECTOR_COMBINATOR_CELL: @@ -650,526 +867,439 @@ lxb_selectors_state_find(lxb_selectors_t *selectors, return NULL; } - return lxb_selectors_state_find_check(selectors, node, selector, entry); + if (node == NULL) { + selectors->state = lxb_selectors_state_not_found; + } + else { + selectors->current->entry->node = node; + } + + return selectors->current->entry; } static lxb_selectors_entry_t * -lxb_selectors_state_find_check(lxb_selectors_t *selectors, const xmlNode *node, - const lxb_css_selector_t *selector, - lxb_selectors_entry_t *entry) +lxb_selectors_state_find_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) { - lxb_selectors_entry_t *next; - lxb_selectors_nested_t *current; - - if (node == NULL) { - - try_next: - - if (entry->next == NULL) { - - try_next_list: - - if (selector->list->next == NULL) { - return NULL; - } - - /* - * Try the following selectors from the selector list. - */ + const xmlNode *node; - if (entry->following != NULL) { - entry->following->node = entry->node; + selectors->state = lxb_selectors_state_found_check_forward; - if (selectors->current->parent == NULL) { - selectors->first = entry->following; - } + switch (entry->combinator) { + case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: + node = lxb_selectors_descendant_forward(selectors, entry, + entry->node); + break; - return entry->following; - } + case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: + node = lxb_selectors_close_forward(selectors, entry, + entry->node); + break; - next = lexbor_dobject_calloc(selectors->objs); + case LXB_CSS_SELECTOR_COMBINATOR_CHILD: + node = lxb_selectors_child_forward(selectors, entry, entry->node); + break; - next->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - next->selector = selector->list->next->last; - next->node = entry->node; + case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: + node = lxb_selectors_sibling_forward(selectors, entry, entry->node); + break; - entry->following = next; + case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: + node = lxb_selectors_following_forward(selectors, entry, + entry->node); + break; - if (selectors->current->parent == NULL) { - selectors->first = next; - } + case LXB_CSS_SELECTOR_COMBINATOR_CELL: + default: + selectors->status = LXB_STATUS_ERROR; + return NULL; + } - return next; - } + if (node == NULL) { + try_next: do { - entry = entry->next; - - while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE) { - if (entry->next == NULL) { - selector = entry->selector; - goto try_next; - } - - entry = entry->next; + if (entry->prev == NULL) { + return lxb_selectors_next_list_forward(selectors, entry); } - switch (entry->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - node = entry->node->parent; - - if (node == NULL - || !CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) - { - node = NULL; - } - - break; - - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = entry->node->prev; - break; - - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - node = NULL; - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CELL: - default: - selectors->status = LXB_STATUS_ERROR; - return NULL; - } + entry = entry->prev; } - while (node == NULL); + while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE); - entry->node = node; + if (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_SIBLING) { + goto try_next; + } - return entry; + selectors->current->entry = entry; + selectors->state = lxb_selectors_state_find_forward; + } + else { + selectors->current->entry->node = node; } - if (selector->prev == NULL) { - current = selectors->current; - - selectors->status = current->cb(current->entry->node, - selector->list->specificity, - current->ctx); + return selectors->current->entry; +} - if ((selectors->options & LXB_SELECTORS_OPT_MATCH_FIRST) == 0 - && current->parent == NULL) - { - if (selectors->status == LXB_STATUS_OK) { - entry = selectors->first; - goto try_next_list; - } - } +lxb_inline lxb_selectors_entry_t * +lxb_selectors_done(lxb_selectors_t *selectors) +{ + lxb_selectors_nested_t *current = selectors->current; + if (current->parent == NULL) { return NULL; } - if (entry->prev == NULL) { - next = lexbor_dobject_calloc(selectors->objs); + selectors->current = current->parent; - next->combinator = selector->combinator; - next->selector = selector->prev; - next->node = node; + return selectors->current->entry; +} - next->next = entry; - entry->prev = next; +lxb_inline lxb_selectors_entry_t * +lxb_selectors_exit(lxb_selectors_t *selectors) +{ + lxb_selectors_nested_t *current = selectors->current; - return next; + if (current->parent == NULL) { + return NULL; } - entry->prev->node = node; + selectors->state = current->return_state; - return entry->prev; + return current->entry; } static lxb_selectors_entry_t * -lxb_selectors_state_pseudo_class_function(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) +lxb_selectors_state_found_check(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) { - const xmlNode *node, *base; lxb_selectors_nested_t *current; - const lxb_css_selector_list_t *list; - lxb_css_selector_anb_of_t *anb; - const lxb_css_selector_pseudo_t *pseudo; + const xmlNode *node; + lxb_selectors_entry_t *prev; + const lxb_css_selector_t *selector; current = selectors->current; + entry = current->entry; + node = entry->node; - base = lxb_selectors_next_node(current); - if (base == NULL) { - goto not_found; - } - - pseudo = ¤t->parent->last->selector->u.pseudo; - - switch (pseudo->type) { - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS: - list = (lxb_css_selector_list_t *) pseudo->data; - node = lxb_selectors_state_has_relative(base, list->first); - - if (node == NULL) { - selectors->current = selectors->current->parent; - entry = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, NULL, - entry->selector, entry); - } - - current->root = base; - - current->entry->selector = list->last; - current->entry->node = node; - current->return_state = lxb_selectors_state_after_find_has; - current->cb = lxb_selectors_cb_ok; - current->ctx = ¤t->found; - current->found = false; - - selectors->state = lxb_selectors_state_find; + if (entry->prev == NULL) { + selector = entry->selector; - return entry; + while (selector->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE + && selector->prev != NULL) + { + selector = selector->prev; + } - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE: - current->entry->selector = ((lxb_css_selector_list_t *) pseudo->data)->last; - current->entry->node = base; - current->return_state = lxb_selectors_state_after_find; - current->cb = lxb_selectors_cb_ok; - current->ctx = ¤t->found; - current->found = false; + if (selector->prev == NULL) { + return lxb_selectors_state_found(selectors, entry); + } - selectors->state = lxb_selectors_state_find; + prev = lxb_selectors_state_entry_create(selectors, selector, + entry, node); + current->entry = prev; + selectors->state = lxb_selectors_state_find; - return entry; + return prev; + } - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT: - current->entry->selector = ((lxb_css_selector_list_t *) pseudo->data)->last; - current->entry->node = base; - current->return_state = lxb_selectors_state_after_find; - current->cb = lxb_selectors_cb_not; - current->ctx = ¤t->found; - current->found = true; + selectors->state = lxb_selectors_state_find; - selectors->state = lxb_selectors_state_find; + current->entry = entry->prev; + entry->prev->node = node; - return entry; + return entry->prev; +} - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD: - anb = pseudo->data; +static lxb_selectors_entry_t * +lxb_selectors_state_found_check_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ + lxb_selectors_nested_t *current; + const xmlNode *node; + lxb_selectors_entry_t *next; + const lxb_css_selector_t *selector; - current->entry->selector = anb->of->last; - current->entry->node = base; - current->return_state = lxb_selectors_state_after_nth_child; - current->cb = lxb_selectors_cb_ok; - current->ctx = ¤t->found; - current->root = base; - current->index = 0; - current->found = false; + current = selectors->current; + entry = current->entry; + node = entry->node; - selectors->state = lxb_selectors_state_find; + if (entry->next == NULL) { + selector = entry->selector; - return entry; + if (selector->next == NULL) { + return lxb_selectors_state_found_forward(selectors, entry); + } - /* - * This one can only happen if the user has somehow messed up the - * selector. - */ + next = lxb_selectors_state_entry_create_forward(selectors, selector, + entry, node); + current->entry = next; + selectors->state = lxb_selectors_state_find_forward; - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL: - default: - break; + return next; } -not_found: - - selectors->current = selectors->current->parent; - entry = selectors->current->last; + selectors->state = lxb_selectors_state_find_forward; - selectors->state = lxb_selectors_state_find; + current->entry = entry->next; + entry->next->node = node; - return lxb_selectors_state_find_check(selectors, NULL, - entry->selector, entry); + return entry->next; } -static const xmlNode * -lxb_selectors_next_node(lxb_selectors_nested_t *main) +static lxb_selectors_entry_t * +lxb_selectors_state_found(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) { - const xmlNode *node = main->entry->node; - - switch (main->parent->last->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - if (node->parent == NULL - || !CMP_NODE_TYPE(node->parent, XML_ELEMENT_NODE)) - { - return NULL; - } - - return node->parent; + lxb_selectors_nested_t *current; + const lxb_css_selector_t *selector; - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - return node; + current = selectors->current; + selector = current->entry->selector; - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->prev; - break; + selectors->state = lxb_selectors_state_find; - default: - return NULL; - } + selectors->status = current->cb(current->root, + selector->list->specificity, + current->ctx); - while (node != NULL) { - if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { - break; + if ((selectors->options & LXB_SELECTORS_OPT_MATCH_FIRST) == 0 + && current->parent == NULL) + { + if (selectors->status == LXB_STATUS_OK) { + entry = selectors->current->first; + return lxb_selectors_next_list(selectors, entry); } - - node = node->prev; } - return node; + return lxb_selectors_done(selectors); } -static const xmlNode * -lxb_selectors_state_has_relative(const xmlNode *node, - const lxb_css_selector_t *selector) +static lxb_selectors_entry_t * +lxb_selectors_state_found_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) { - const xmlNode *root = node; - - switch (selector->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - node = node->children; - break; - - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->next; - break; + lxb_selectors_nested_t *current; + const lxb_css_selector_t *selector; - default: - return NULL; - } + current = selectors->current; + selector = current->entry->selector; - while (node != NULL) { - if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { - break; - } + selectors->state = lxb_selectors_state_find_forward; - while (node != root && node->next == NULL && node->parent != NULL) { - node = node->parent; - } + selectors->status = current->cb(current->root, + selector->list->specificity, + current->ctx); - if (node == root) { - return NULL; + if ((selectors->options & LXB_SELECTORS_OPT_MATCH_FIRST) == 0 + && current->parent == NULL) + { + if (selectors->status == LXB_STATUS_OK) { + entry = selectors->current->first; + return lxb_selectors_next_list_forward(selectors, entry); } - - node = node->next; } - return node; + return lxb_selectors_done(selectors); } + static lxb_selectors_entry_t * -lxb_selectors_state_after_find_has(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) +lxb_selectors_state_not_found(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) { - const xmlNode *node; - lxb_selectors_entry_t *parent; lxb_selectors_nested_t *current; - if (selectors->current->found) { - node = selectors->current->root; - - selectors->current = selectors->current->parent; - parent = selectors->current->last; + current = selectors->current; + entry = current->entry; - selectors->state = lxb_selectors_state_find; +try_next: - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); + if (entry->next == NULL) { + return lxb_selectors_next_list(selectors, entry); } - current = selectors->current; - node = entry->node; - - switch (entry->selector->list->first->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - if (node->children != NULL) { - node = node->children; - } - else { + entry = entry->next; - next: + while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE) { + if (entry->next == NULL) { + goto try_next; + } - while (node != current->root && node->next == NULL) { - node = node->parent; - } + entry = entry->next; + } - if (node == current->root) { - goto failed; - } + switch (entry->combinator) { + case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: + case LXB_CSS_SELECTOR_COMBINATOR_CHILD: + case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: + goto try_next; - node = node->next; - } + default: + break; + } - if (!CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { - goto next; - } + current->entry = entry; + selectors->state = lxb_selectors_state_find; - break; + return entry; +} - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->next; +static lxb_selectors_entry_t * +lxb_selectors_state_not_found_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ +try_next: - while (node != NULL && !CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { - node = node->next; - } + if (entry->prev == NULL) { + return lxb_selectors_next_list_forward(selectors, entry); + } - if (node == NULL) { - goto failed; - } + while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE) { + if (entry->prev == NULL) { + goto try_next; + } - break; + entry = entry->prev; + } - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - goto failed; + if (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_SIBLING) { + if (entry->prev != NULL) { + entry = entry->prev; + } - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - case LXB_CSS_SELECTOR_COMBINATOR_CELL: - default: - selectors->status = LXB_STATUS_ERROR; - return NULL; + goto try_next; } - entry->node = node; - selectors->state = lxb_selectors_state_find; + selectors->current->entry = entry; + selectors->state = lxb_selectors_state_find_forward; return entry; +} -failed: - - selectors->current = selectors->current->parent; - parent = selectors->current->last; +static lxb_selectors_entry_t * +lxb_selectors_next_list(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ + if (entry->selector->list->next == NULL) { + return lxb_selectors_exit(selectors); + } selectors->state = lxb_selectors_state_find; - return lxb_selectors_state_find_check(selectors, NULL, - parent->selector, parent); + /* + * Try the following selectors from the selector list. + */ + + return lxb_selectors_make_following(selectors, entry); } +static lxb_selectors_entry_t * +lxb_selectors_next_list_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ + if (entry->selector->list->next == NULL) { + return lxb_selectors_exit(selectors); + } + + selectors->state = lxb_selectors_state_find_forward; + + /* + * Try the following selectors from the selector list. + */ + + return lxb_selectors_make_following_forward(selectors, entry); +} static lxb_selectors_entry_t * -lxb_selectors_state_after_find(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) +lxb_selectors_make_following(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) { - const xmlNode *node; - lxb_selectors_entry_t *parent; + lxb_selectors_entry_t *next; lxb_selectors_nested_t *current; + const lxb_css_selector_t *selector; + selector = entry->selector; current = selectors->current; - if (current->found) { - node = entry->node; + if (entry->following != NULL) { + entry->following->node = current->root; + current->first = entry->following; + current->entry = entry->following; - selectors->current = current->parent; - parent = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); + return entry->following; } - node = entry->node; + next = lxb_selectors_entry_make_first(selectors, + selector->list->next->last); - switch (current->parent->last->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - if (node->parent != NULL - && CMP_NODE_TYPE(node->parent, XML_ELEMENT_NODE)) - { - node = node->parent; - } - else { - node = NULL; - } + next->node = current->root; - break; + entry->following = next; + current->first = next; + current->entry = next; - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->prev; + return next; +} - while (node != NULL && !CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { - node = node->prev; - } +static lxb_selectors_entry_t * +lxb_selectors_make_following_forward(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ + lxb_selectors_entry_t *next; + lxb_selectors_nested_t *current; + const lxb_css_selector_t *selector; - break; + selector = entry->selector; + current = selectors->current; - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - node = NULL; - break; + if (entry->following != NULL) { + entry->following->node = current->root; + current->first = entry->following; + current->entry = entry->following; - case LXB_CSS_SELECTOR_COMBINATOR_CELL: - default: - selectors->status = LXB_STATUS_ERROR; - return NULL; + return entry->following; } - if (node == NULL) { - selectors->current = current->parent; - parent = selectors->current->last; - - selectors->state = lxb_selectors_state_find; + next = lexbor_dobject_calloc(selectors->objs); - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); - } + next->selector = selector->list->next->first; + next->node = current->root; + next->combinator = next->selector->combinator; - entry->node = node; - selectors->state = lxb_selectors_state_find; + entry->following = next; + current->first = next; + current->entry = next; - return entry; + return next; } static lxb_selectors_entry_t * -lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) +lxb_selectors_state_after_find(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) { - bool found; - const xmlNode *node; - lxb_selectors_entry_t *parent; - lxb_selectors_nested_t *current; - const lxb_css_selector_t *selector; - const lxb_css_selector_pseudo_t *pseudo; + selectors->current = selectors->current->parent; - current = selectors->current; - selector = current->parent->last->selector; - pseudo = &selector->u.pseudo; + lxb_selectors_switch_to_not_found(selectors, selectors->current); - node = entry->node; + return selectors->current->entry; +} - if (current->found) { - current->index += 1; - } - else if (current->root == node) { - node = NULL; - goto done; - } +static lxb_selectors_entry_t * +lxb_selectors_state_after_not(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ + selectors->current = selectors->current->parent; + lxb_selectors_switch_to_found_check(selectors, selectors->current); + + return selectors->current->entry; +} + +lxb_inline const xmlNode * +lxb_selectors_state_nth_child_node(const lxb_css_selector_pseudo_t *pseudo, + const xmlNode *node) +{ if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD) { node = node->prev; @@ -1193,46 +1323,98 @@ lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors, } } + return node; +} + +lxb_inline lxb_selectors_entry_t * +lxb_selectors_state_nth_child_done(lxb_selectors_t *selectors, + const lxb_css_selector_pseudo_t *pseudo, + size_t index) +{ + if (lxb_selectors_anb_calc(pseudo->data, index)) { + lxb_selectors_switch_to_found_check(selectors, selectors->current); + } + else { + lxb_selectors_switch_to_not_found(selectors, selectors->current); + } + + return selectors->current->entry; +} + +static lxb_selectors_entry_t * +lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ + const xmlNode *node; + lxb_selectors_nested_t *current; + const lxb_css_selector_pseudo_t *pseudo; + + current = selectors->current; + + if (current->index == 0) { + selectors->state = lxb_selectors_state_not_found; + selectors->current = selectors->current->parent; + + return selectors->current->entry; + } + + pseudo = ¤t->parent->entry->selector->u.pseudo; + node = lxb_selectors_state_nth_child_node(pseudo, current->root); + if (node == NULL) { - goto done; + selectors->current = selectors->current->parent; + + return lxb_selectors_state_nth_child_done(selectors, pseudo, + current->index); } - entry->node = node; - current->found = false; + current->root = node; + current->entry->node = node; + selectors->state = lxb_selectors_state_find; return entry; +} -done: +static lxb_selectors_entry_t * +lxb_selectors_state_nth_child_found(lxb_selectors_t *selectors, + lxb_selectors_entry_t *entry) +{ + const xmlNode *node; + lxb_selectors_nested_t *current; + const lxb_css_selector_pseudo_t *pseudo; - if (current->index > 0) { - found = lxb_selectors_anb_calc(pseudo->data, current->index); + current = entry->nested; + pseudo = &entry->selector->u.pseudo; + node = lxb_selectors_state_nth_child_node(pseudo, current->root); - node = (found) ? current->root : NULL; + if (node == NULL) { + return lxb_selectors_state_nth_child_done(selectors, pseudo, + current->index); } - selectors->state = lxb_selectors_state_find; - selectors->current = selectors->current->parent; + current->root = node; + current->entry->node = node; - parent = selectors->current->last; + selectors->current = current; + selectors->state = lxb_selectors_state_find; - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); + return current->entry; } static bool lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, const xmlNode *node) + const xmlNode *node) { - switch (selector->type) { + switch (entry->selector->type) { case LXB_CSS_SELECTOR_TYPE_ANY: return true; case LXB_CSS_SELECTOR_TYPE_ELEMENT: - return lxb_selectors_match_element(selector, node, entry); + return lxb_selectors_match_element(entry->selector, node, entry); case LXB_CSS_SELECTOR_TYPE_ID: - return lxb_selectors_match_id(selector, node, selectors->options & LXB_SELECTORS_OPT_QUIRKS_MODE); + return lxb_selectors_match_id(entry->selector, node, selectors->options & LXB_SELECTORS_OPT_QUIRKS_MODE); case LXB_CSS_SELECTOR_TYPE_CLASS: { const xmlAttr *dom_attr = lxb_selectors_adapted_attr(node, (const lxb_char_t *) "class"); @@ -1246,24 +1428,23 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, dom_lxb_str_wrapper_release(&trg); return false; } - bool ret = lxb_selectors_match_class(&trg.str, - &selector->name, selectors->options & LXB_SELECTORS_OPT_QUIRKS_MODE); + &entry->selector->name, selectors->options & LXB_SELECTORS_OPT_QUIRKS_MODE); dom_lxb_str_wrapper_release(&trg); return ret; } case LXB_CSS_SELECTOR_TYPE_ATTRIBUTE: - return lxb_selectors_match_attribute(selector, node, entry); + return lxb_selectors_match_attribute(entry->selector, node, entry); case LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS: - return lxb_selectors_pseudo_class(selector, node); + return lxb_selectors_pseudo_class(entry->selector, node); case LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS_FUNCTION: - return lxb_selectors_pseudo_class_function(selector, node); - + return lxb_selectors_pseudo_class_function(selectors, + entry->selector, node); case LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT: - return lxb_selectors_pseudo_element(selector, node); + return lxb_selectors_pseudo_element(entry->selector, node); case LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT_FUNCTION: return false; @@ -1714,24 +1895,118 @@ lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, return false; } +static lxb_selectors_nested_t * +lxb_selectors_nested_make(lxb_selectors_t *selectors, const xmlNode *node, + lxb_css_selector_t *selector, bool forward) +{ + lxb_selectors_entry_t *next; + lxb_selectors_entry_t *entry; + + entry = selectors->current->entry; + entry->node = node; + + if (entry->nested == NULL) { + if (!forward) { + next = lxb_selectors_entry_make_first(selectors, selector); + } + else { + next = lexbor_dobject_calloc(selectors->objs); + + next->combinator = selector->combinator; + next->selector = selector; + } + + entry->nested = lexbor_dobject_calloc(selectors->nested); + + entry->nested->top = next; + entry->nested->parent = selectors->current; + entry->nested->forward = forward; + } + + selectors->current = entry->nested; + entry->nested->entry = entry->nested->top; + entry->nested->first = entry->nested->top; + + selectors->current->root = node; + selectors->current->ctx = selectors; + + return selectors->current; +} + static bool -lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, +lxb_selectors_pseudo_class_function(lxb_selectors_t *selectors, + const lxb_css_selector_t *selector, const xmlNode *node) { size_t index; const xmlNode *base; + lxb_selectors_nested_t *current; + const lxb_css_selector_list_t *list; + const lxb_css_selector_anb_of_t *anb; const lxb_css_selector_pseudo_t *pseudo; pseudo = &selector->u.pseudo; switch (pseudo->type) { + case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS: + list = (lxb_css_selector_list_t *) pseudo->data; + + current = lxb_selectors_nested_make(selectors, node, + list->first, true); + + current->cb = lxb_selectors_cb_ok; + current->return_state = lxb_selectors_state_after_find; + selectors->state = lxb_selectors_state_find_forward; + + break; + + case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT: + case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS: + case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE: + list = (lxb_css_selector_list_t *) pseudo->data; + + current = lxb_selectors_nested_make(selectors, node, list->last, + false); + + current->cb = lxb_selectors_cb_ok; + current->return_state = lxb_selectors_state_after_find; + selectors->state = lxb_selectors_state_find; + + break; + + case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT: + list = (lxb_css_selector_list_t *) pseudo->data; + + current = lxb_selectors_nested_make(selectors, node, list->last, + false); + + current->cb = lxb_selectors_cb_not; + current->return_state = lxb_selectors_state_after_not; + selectors->state = lxb_selectors_state_find; + + break; + case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD: case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD: + anb = pseudo->data; + + if (anb->of != NULL) { + current = lxb_selectors_nested_make(selectors, node, + anb->of->last, false); + + current->return_state = lxb_selectors_state_after_nth_child; + current->cb = lxb_selectors_cb_nth_ok; + current->index = 0; + selectors->state = lxb_selectors_state_find; + + return true; + } + index = 0; if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD) { while (node != NULL) { - if (lxb_selectors_adapted_is_matchable_child(node)) + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { index++; } @@ -1741,7 +2016,7 @@ lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, } else { while (node != NULL) { - if (lxb_selectors_adapted_is_matchable_child(node)) + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { index++; } @@ -1759,7 +2034,7 @@ lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE) { while (node != NULL) { - if(lxb_selectors_adapted_is_matchable_child(node) + if(CMP_NODE_TYPE(node, XML_ELEMENT_NODE) && xmlStrEqual(node->name, base->name) && lxb_selectors_adapted_cmp_ns(node, base)) { @@ -1771,7 +2046,7 @@ lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, } else { while (node != NULL) { - if(lxb_selectors_adapted_is_matchable_child(node) + if(CMP_NODE_TYPE(node, XML_ELEMENT_NODE) && xmlStrEqual(node->name, base->name) && lxb_selectors_adapted_cmp_ns(node, base)) { @@ -1789,10 +2064,10 @@ lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL: case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL: default: - break; + return false; } - return false; + return true; } static bool @@ -1843,7 +2118,7 @@ lxb_selectors_pseudo_class_disabled(const xmlNode *node) const xmlNode *fieldset = node; node = node->parent; - while (node != NULL && lxb_selectors_adapted_is_matchable_child(node)) { + while (node != NULL && CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { /* node is a disabled fieldset that is an ancestor of fieldset */ if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token) && lxb_selectors_adapted_cmp_local_name_literal(node, "fieldset") @@ -1887,7 +2162,7 @@ lxb_selectors_pseudo_class_first_child(const xmlNode *node) node = node->prev; while (node != NULL) { - if (lxb_selectors_adapted_is_matchable_child(node)) + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { return false; } @@ -1905,7 +2180,7 @@ lxb_selectors_pseudo_class_first_of_type(const xmlNode *node) node = node->prev; while (node) { - if (lxb_selectors_adapted_is_matchable_child(node) + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE) && xmlStrEqual(node->name, root->name) && lxb_selectors_adapted_cmp_ns(node, root)) { @@ -1924,7 +2199,7 @@ lxb_selectors_pseudo_class_last_child(const xmlNode *node) node = node->next; while (node != NULL) { - if (lxb_selectors_adapted_is_matchable_child(node)) + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE)) { return false; } @@ -1942,7 +2217,7 @@ lxb_selectors_pseudo_class_last_of_type(const xmlNode *node) node = node->next; while (node) { - if (lxb_selectors_adapted_is_matchable_child(node) + if (CMP_NODE_TYPE(node, XML_ELEMENT_NODE) && xmlStrEqual(node->name, root->name) && lxb_selectors_adapted_cmp_ns(node, root)) { @@ -1997,7 +2272,10 @@ static lxb_status_t lxb_selectors_cb_ok(const xmlNode *node, lxb_css_selector_specificity_t spec, void *ctx) { - *((bool *) ctx) = true; + lxb_selectors_t *selectors = ctx; + + lxb_selectors_switch_to_found_check(selectors, selectors->current->parent); + return LXB_STATUS_OK; } @@ -2005,6 +2283,21 @@ static lxb_status_t lxb_selectors_cb_not(const xmlNode *node, lxb_css_selector_specificity_t spec, void *ctx) { - *((bool *) ctx) = false; + lxb_selectors_t *selectors = ctx; + + lxb_selectors_switch_to_not_found(selectors, selectors->current->parent); + + return LXB_STATUS_OK; +} + +static lxb_status_t +lxb_selectors_cb_nth_ok(const xmlNode *node, + lxb_css_selector_specificity_t spec, void *ctx) +{ + lxb_selectors_t *selectors = ctx; + + selectors->current->index += 1; + selectors->state = lxb_selectors_state_nth_child_found; + return LXB_STATUS_OK; } diff --git a/ext/dom/lexbor/selectors-adapted/selectors.h b/ext/dom/lexbor/selectors-adapted/selectors.h index a4aea04887f4c..c0f76cce3d5cc 100644 --- a/ext/dom/lexbor/selectors-adapted/selectors.h +++ b/ext/dom/lexbor/selectors-adapted/selectors.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2024 Alexander Borisov + * Copyright (C) 2021-2025 Alexander Borisov * * Author: Alexander Borisov * Adapted for PHP libxml2 by: Niels Dossche @@ -100,11 +100,13 @@ struct lxb_selectors_nested { void *ctx; const xmlNode *root; - lxb_selectors_entry_t *last; lxb_selectors_nested_t *parent; + lxb_selectors_entry_t *first; + lxb_selectors_entry_t *top; size_t index; - bool found; + + bool forward; }; struct lxb_selectors { @@ -113,7 +115,6 @@ struct lxb_selectors { lexbor_dobject_t *nested; lxb_selectors_nested_t *current; - lxb_selectors_entry_t *first; lxb_selectors_opt_t options; lxb_status_t status; diff --git a/ext/dom/namednodemap.c b/ext/dom/namednodemap.c index 953731ad84487..4964f836407cb 100644 --- a/ext/dom/namednodemap.c +++ b/ext/dom/namednodemap.c @@ -35,10 +35,6 @@ zend_long php_dom_get_namednodemap_length(dom_object *obj) { dom_nnodemap_object *objmap = obj->ptr; - if (!objmap) { - return 0; - } - return objmap->handler->length(objmap); } @@ -67,7 +63,7 @@ PHP_METHOD(DOMNamedNodeMap, getNamedItem) } dom_nnodemap_object *objmap = Z_DOMOBJ_P(ZEND_THIS)->ptr; - php_dom_obj_map_get_named_item_into_zval(objmap, named, NULL, return_value); + php_dom_obj_map_get_ns_named_item_into_zval(objmap, named, NULL, return_value); } /* }}} end dom_namednodemap_get_named_item */ @@ -112,7 +108,7 @@ PHP_METHOD(DOMNamedNodeMap, getNamedItemNS) objmap = (dom_nnodemap_object *)intern->ptr; if (objmap != NULL) { - php_dom_obj_map_get_named_item_into_zval(objmap, named, uri, return_value); + php_dom_obj_map_get_ns_named_item_into_zval(objmap, named, uri, return_value); } } /* }}} end dom_namednodemap_get_named_item_ns */ diff --git a/ext/dom/obj_map.c b/ext/dom/obj_map.c index fe71a6f47a38a..9c017c4d11a6b 100644 --- a/ext/dom/obj_map.c +++ b/ext/dom/obj_map.c @@ -24,14 +24,12 @@ #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "php_dom.h" #include "obj_map.h" +#include "token_list.h" static zend_always_inline void objmap_cache_release_cached_obj(dom_nnodemap_object *objmap) { if (objmap->cached_obj) { - /* Since the DOM is a tree there can be no cycles. */ - if (GC_DELREF(&objmap->cached_obj->std) == 0) { - zend_objects_store_del(&objmap->cached_obj->std); - } + OBJ_RELEASE(&objmap->cached_obj->std); objmap->cached_obj = NULL; objmap->cached_obj_index = 0; } @@ -43,6 +41,30 @@ static zend_always_inline void reset_objmap_cache(dom_nnodemap_object *objmap) objmap->cached_length = -1; } +static bool dom_matches_class_name(const dom_nnodemap_object *map, const xmlNode *nodep) +{ + bool ret = false; + + if (nodep->type == XML_ELEMENT_NODE) { + xmlAttrPtr classes = xmlHasNsProp(nodep, BAD_CAST "class", NULL); + if (classes != NULL) { + bool should_free; + xmlChar *value = php_libxml_attr_value(classes, &should_free); + + bool quirks = map->baseobj->document->quirks_mode == PHP_LIBXML_QUIRKS; + if (dom_ordered_set_all_contained(map->array, (const char *) value, quirks)) { + ret = true; + } + + if (should_free) { + xmlFree(value); + } + } + } + + return ret; +} + /************************** * === Length methods === * **************************/ @@ -82,6 +104,20 @@ static zend_long dom_map_get_nodes_length(dom_nnodemap_object *map) return count; } +static zend_long dom_map_get_elements_length(dom_nnodemap_object *map) +{ + zend_long count = 0; + xmlNodePtr nodep = dom_object_get_node(map->baseobj); + if (nodep) { + for (xmlNodePtr curnode = dom_nodelist_iter_start_first_child(nodep); curnode; curnode = curnode->next) { + if (curnode->type == XML_ELEMENT_NODE) { + count++; + } + } + } + return count; +} + static zend_long dom_map_get_by_tag_name_length(dom_nnodemap_object *map) { xmlNodePtr nodep = dom_object_get_node(map->baseobj); @@ -95,6 +131,24 @@ static zend_long dom_map_get_by_tag_name_length(dom_nnodemap_object *map) return count; } +static zend_long dom_map_get_by_class_name_length(dom_nnodemap_object *map) +{ + xmlNodePtr nodep = dom_object_get_node(map->baseobj); + zend_long count = 0; + if (nodep) { + xmlNodePtr basep = nodep; + nodep = php_dom_first_child_of_container_node(basep); + + while (nodep != NULL) { + if (dom_matches_class_name(map, nodep)) { + count++; + } + nodep = php_dom_next_in_tree_order(nodep, basep); + } + } + return count; +} + static zend_long dom_map_get_zero_length(dom_nnodemap_object *map) { return 0; @@ -223,6 +277,52 @@ static void dom_map_get_nodes_item(dom_nnodemap_object *map, zend_long index, zv } } +static void dom_map_get_elements_item(dom_nnodemap_object *map, zend_long index, zval *return_value) +{ + xmlNodePtr nodep = dom_object_get_node(map->baseobj); + xmlNodePtr itemnode = NULL; + if (nodep && index >= 0) { + dom_node_idx_pair start_point = dom_obj_map_get_start_point(map, nodep, index); + if (start_point.node) { + /* Guaranteed to be an element */ + itemnode = start_point.node; + } else { + /* Fetch first element child */ + itemnode = nodep->children; + while (itemnode && itemnode->type != XML_ELEMENT_NODE) { + itemnode = itemnode->next; + } + } + + for (; start_point.index > 0 && itemnode; --start_point.index) { + do { + itemnode = itemnode->next; + } while (itemnode && itemnode->type != XML_ELEMENT_NODE); + } + if (itemnode && itemnode->type != XML_ELEMENT_NODE) { + itemnode = NULL; + } + } + dom_ret_node_to_zobj(map, itemnode, return_value); + if (itemnode) { + dom_map_cache_obj(map, itemnode, index, return_value); + } +} + +static void dom_map_collection_named_item_elements_iter(dom_nnodemap_object *map, php_dom_obj_map_collection_iter *iter) +{ + if (iter->candidate != iter->basep->children) { + iter->candidate = iter->candidate->next; + } + while (iter->candidate && iter->candidate->type != XML_ELEMENT_NODE) { + iter->candidate = iter->candidate->next; + } +} + +static void dom_map_collection_named_item_null(dom_nnodemap_object *map, php_dom_obj_map_collection_iter *iter) +{ +} + static void dom_map_get_by_tag_name_item(dom_nnodemap_object *map, zend_long index, zval *return_value) { xmlNodePtr nodep = dom_object_get_node(map->baseobj); @@ -239,6 +339,54 @@ static void dom_map_get_by_tag_name_item(dom_nnodemap_object *map, zend_long ind } } +static void dom_map_get_by_class_name_item(dom_nnodemap_object *map, zend_long index, zval *return_value) +{ + xmlNodePtr nodep = dom_object_get_node(map->baseobj); + xmlNodePtr itemnode = NULL; + if (nodep && index >= 0) { + dom_node_idx_pair start_point = dom_obj_map_get_start_point(map, nodep, index); + if (start_point.node) { + if (start_point.index > 0) { + /* Only start iteration at next point if we actually have an index to seek to. */ + itemnode = php_dom_next_in_tree_order(start_point.node, nodep); + } else { + itemnode = start_point.node; + } + } else { + itemnode = php_dom_first_child_of_container_node(nodep); + } + + do { + --start_point.index; + while (itemnode != NULL && !dom_matches_class_name(map, itemnode)) { + itemnode = php_dom_next_in_tree_order(itemnode, nodep); + } + } while (start_point.index > 0 && itemnode); + } + dom_ret_node_to_zobj(map, itemnode, return_value); + if (itemnode) { + dom_map_cache_obj(map, itemnode, index, return_value); + } +} + +static void dom_map_collection_named_item_by_tag_name_iter(dom_nnodemap_object *map, php_dom_obj_map_collection_iter *iter) +{ + iter->candidate = dom_get_elements_by_tag_name_ns_raw(iter->basep, iter->candidate, map->ns, map->local, map->local_lower, &iter->cur, iter->next); + iter->next = iter->cur + 1; +} + +static void dom_map_collection_named_item_by_class_name_iter(dom_nnodemap_object *map, php_dom_obj_map_collection_iter *iter) +{ + xmlNodePtr basep = iter->basep; + xmlNodePtr nodep = iter->candidate ? php_dom_next_in_tree_order(iter->candidate, basep) : php_dom_first_child_of_container_node(basep); + + while (nodep != NULL && !dom_matches_class_name(map, nodep)) { + nodep = php_dom_next_in_tree_order(nodep, basep); + } + + iter->candidate = nodep; +} + static void dom_map_get_null_item(dom_nnodemap_object *map, zend_long index, zval *return_value) { RETURN_NULL(); @@ -251,9 +399,6 @@ static void dom_map_get_null_item(dom_nnodemap_object *map, zend_long index, zva zend_long php_dom_get_nodelist_length(dom_object *obj) { dom_nnodemap_object *objmap = obj->ptr; - if (!objmap) { - return 0; - } if (objmap->handler->use_cache) { xmlNodePtr nodep = dom_object_get_node(objmap->baseobj); @@ -333,9 +478,9 @@ void php_dom_obj_map_get_item_into_zval(dom_nnodemap_object *objmap, zend_long i } } -void php_dom_obj_map_get_named_item_into_zval(dom_nnodemap_object *objmap, const zend_string *named, const char *ns, zval *return_value) +void php_dom_obj_map_get_ns_named_item_into_zval(dom_nnodemap_object *objmap, const zend_string *named, const char *ns, zval *return_value) { - xmlNodePtr itemnode = objmap->handler->get_named_item(objmap, named, ns); + xmlNodePtr itemnode = objmap->handler->get_ns_named_item(objmap, named, ns); if (itemnode) { DOM_RET_OBJ(itemnode, objmap->baseobj); } else { @@ -347,17 +492,17 @@ void php_dom_obj_map_get_named_item_into_zval(dom_nnodemap_object *objmap, const * === Named item === * **********************/ -static xmlNodePtr dom_map_get_named_item_entity(dom_nnodemap_object *map, const zend_string *named, const char *ns) +static xmlNodePtr dom_map_get_ns_named_item_entity(dom_nnodemap_object *map, const zend_string *named, const char *ns) { return xmlHashLookup(map->ht, BAD_CAST ZSTR_VAL(named)); } -static bool dom_map_has_named_item_xmlht(dom_nnodemap_object *map, const zend_string *named, const char *ns) +static bool dom_map_has_ns_named_item_xmlht(dom_nnodemap_object *map, const zend_string *named, const char *ns) { - return dom_map_get_named_item_entity(map, named, ns) != NULL; + return dom_map_get_ns_named_item_entity(map, named, ns) != NULL; } -static xmlNodePtr dom_map_get_named_item_notation(dom_nnodemap_object *map, const zend_string *named, const char *ns) +static xmlNodePtr dom_map_get_ns_named_item_notation(dom_nnodemap_object *map, const zend_string *named, const char *ns) { xmlNotationPtr notation = xmlHashLookup(map->ht, BAD_CAST ZSTR_VAL(named)); if (notation) { @@ -366,7 +511,7 @@ static xmlNodePtr dom_map_get_named_item_notation(dom_nnodemap_object *map, cons return NULL; } -static xmlNodePtr dom_map_get_named_item_prop(dom_nnodemap_object *map, const zend_string *named, const char *ns) +static xmlNodePtr dom_map_get_ns_named_item_prop(dom_nnodemap_object *map, const zend_string *named, const char *ns) { xmlNodePtr nodep = dom_object_get_node(map->baseobj); if (nodep) { @@ -383,17 +528,17 @@ static xmlNodePtr dom_map_get_named_item_prop(dom_nnodemap_object *map, const ze return NULL; } -static bool dom_map_has_named_item_prop(dom_nnodemap_object *map, const zend_string *named, const char *ns) +static bool dom_map_has_ns_named_item_prop(dom_nnodemap_object *map, const zend_string *named, const char *ns) { - return dom_map_get_named_item_prop(map, named, ns) != NULL; + return dom_map_get_ns_named_item_prop(map, named, ns) != NULL; } -static xmlNodePtr dom_map_get_named_item_null(dom_nnodemap_object *map, const zend_string *named, const char *ns) +static xmlNodePtr dom_map_get_ns_named_item_null(dom_nnodemap_object *map, const zend_string *named, const char *ns) { return NULL; } -static bool dom_map_has_named_item_null(dom_nnodemap_object *map, const zend_string *named, const char *ns) +static bool dom_map_has_ns_named_item_null(dom_nnodemap_object *map, const zend_string *named, const char *ns) { return false; } @@ -405,8 +550,9 @@ static bool dom_map_has_named_item_null(dom_nnodemap_object *map, const zend_str const php_dom_obj_map_handler php_dom_obj_map_attributes = { .length = dom_map_get_prop_length, .get_item = dom_map_get_attributes_item, - .get_named_item = dom_map_get_named_item_prop, - .has_named_item = dom_map_has_named_item_prop, + .get_ns_named_item = dom_map_get_ns_named_item_prop, + .has_ns_named_item = dom_map_has_ns_named_item_prop, + .collection_named_item_iter = NULL, .use_cache = false, .nameless = false, }; @@ -414,8 +560,19 @@ const php_dom_obj_map_handler php_dom_obj_map_attributes = { const php_dom_obj_map_handler php_dom_obj_map_by_tag_name = { .length = dom_map_get_by_tag_name_length, .get_item = dom_map_get_by_tag_name_item, - .get_named_item = dom_map_get_named_item_null, - .has_named_item = dom_map_has_named_item_null, + .get_ns_named_item = dom_map_get_ns_named_item_null, + .has_ns_named_item = dom_map_has_ns_named_item_null, + .collection_named_item_iter = dom_map_collection_named_item_by_tag_name_iter, + .use_cache = true, + .nameless = true, +}; + +const php_dom_obj_map_handler php_dom_obj_map_by_class_name = { + .length = dom_map_get_by_class_name_length, + .get_item = dom_map_get_by_class_name_item, + .get_ns_named_item = dom_map_get_ns_named_item_null, + .has_ns_named_item = dom_map_has_ns_named_item_null, + .collection_named_item_iter = dom_map_collection_named_item_by_class_name_iter, .use_cache = true, .nameless = true, }; @@ -423,8 +580,9 @@ const php_dom_obj_map_handler php_dom_obj_map_by_tag_name = { const php_dom_obj_map_handler php_dom_obj_map_child_nodes = { .length = dom_map_get_nodes_length, .get_item = dom_map_get_nodes_item, - .get_named_item = dom_map_get_named_item_null, - .has_named_item = dom_map_has_named_item_null, + .get_ns_named_item = dom_map_get_ns_named_item_null, + .has_ns_named_item = dom_map_has_ns_named_item_null, + .collection_named_item_iter = NULL, .use_cache = true, .nameless = true, }; @@ -432,8 +590,9 @@ const php_dom_obj_map_handler php_dom_obj_map_child_nodes = { const php_dom_obj_map_handler php_dom_obj_map_nodeset = { .length = dom_map_get_nodeset_length, .get_item = dom_map_get_nodeset_item, - .get_named_item = dom_map_get_named_item_null, - .has_named_item = dom_map_has_named_item_null, + .get_ns_named_item = dom_map_get_ns_named_item_null, + .has_ns_named_item = dom_map_has_ns_named_item_null, + .collection_named_item_iter = NULL, .use_cache = false, .nameless = true, }; @@ -441,8 +600,9 @@ const php_dom_obj_map_handler php_dom_obj_map_nodeset = { const php_dom_obj_map_handler php_dom_obj_map_entities = { .length = dom_map_get_xmlht_length, .get_item = dom_map_get_entity_item, - .get_named_item = dom_map_get_named_item_entity, - .has_named_item = dom_map_has_named_item_xmlht, + .get_ns_named_item = dom_map_get_ns_named_item_entity, + .has_ns_named_item = dom_map_has_ns_named_item_xmlht, + .collection_named_item_iter = NULL, .use_cache = false, .nameless = false, }; @@ -450,17 +610,29 @@ const php_dom_obj_map_handler php_dom_obj_map_entities = { const php_dom_obj_map_handler php_dom_obj_map_notations = { .length = dom_map_get_xmlht_length, .get_item = dom_map_get_notation_item, - .get_named_item = dom_map_get_named_item_notation, - .has_named_item = dom_map_has_named_item_xmlht, + .get_ns_named_item = dom_map_get_ns_named_item_notation, + .has_ns_named_item = dom_map_has_ns_named_item_xmlht, + .collection_named_item_iter = NULL, .use_cache = false, .nameless = false, }; +const php_dom_obj_map_handler php_dom_obj_map_child_elements = { + .length = dom_map_get_elements_length, + .get_item = dom_map_get_elements_item, + .get_ns_named_item = dom_map_get_ns_named_item_null, + .has_ns_named_item = dom_map_has_ns_named_item_null, + .collection_named_item_iter = dom_map_collection_named_item_elements_iter, + .use_cache = true, + .nameless = true, +}; + const php_dom_obj_map_handler php_dom_obj_map_noop = { .length = dom_map_get_zero_length, .get_item = dom_map_get_null_item, - .get_named_item = dom_map_get_named_item_null, - .has_named_item = dom_map_has_named_item_null, + .get_ns_named_item = dom_map_get_ns_named_item_null, + .has_ns_named_item = dom_map_has_ns_named_item_null, + .collection_named_item_iter = dom_map_collection_named_item_null, .use_cache = false, .nameless = true, }; diff --git a/ext/dom/obj_map.h b/ext/dom/obj_map.h index e1de9addd98f2..e7231eb7b10a8 100644 --- a/ext/dom/obj_map.h +++ b/ext/dom/obj_map.h @@ -19,11 +19,17 @@ typedef struct dom_nnodemap_object dom_nnodemap_object; +typedef struct php_dom_obj_map_collection_iter { + zend_long cur, next; + xmlNodePtr candidate, basep; +} php_dom_obj_map_collection_iter; + typedef struct php_dom_obj_map_handler { zend_long (*length)(dom_nnodemap_object *); void (*get_item)(dom_nnodemap_object *, zend_long, zval *); - xmlNodePtr (*get_named_item)(dom_nnodemap_object *, const zend_string *, const char *); - bool (*has_named_item)(dom_nnodemap_object *, const zend_string *, const char *); + xmlNodePtr (*get_ns_named_item)(dom_nnodemap_object *, const zend_string *, const char *); + bool (*has_ns_named_item)(dom_nnodemap_object *, const zend_string *, const char *); + void (*collection_named_item_iter)(dom_nnodemap_object *, php_dom_obj_map_collection_iter *); bool use_cache; bool nameless; } php_dom_obj_map_handler; @@ -51,12 +57,14 @@ typedef struct dom_nnodemap_object { } dom_nnodemap_object; void php_dom_create_obj_map(dom_object *basenode, dom_object *intern, xmlHashTablePtr ht, zend_string *local, zend_string *ns, const php_dom_obj_map_handler *handler); -void php_dom_obj_map_get_named_item_into_zval(dom_nnodemap_object *objmap, const zend_string *named, const char *ns, zval *return_value); +void php_dom_obj_map_get_ns_named_item_into_zval(dom_nnodemap_object *objmap, const zend_string *named, const char *ns, zval *return_value); void php_dom_obj_map_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value); zend_long php_dom_get_nodelist_length(dom_object *obj); extern const php_dom_obj_map_handler php_dom_obj_map_attributes; extern const php_dom_obj_map_handler php_dom_obj_map_by_tag_name; +extern const php_dom_obj_map_handler php_dom_obj_map_by_class_name; +extern const php_dom_obj_map_handler php_dom_obj_map_child_elements; extern const php_dom_obj_map_handler php_dom_obj_map_child_nodes; extern const php_dom_obj_map_handler php_dom_obj_map_nodeset; extern const php_dom_obj_map_handler php_dom_obj_map_entities; diff --git a/ext/dom/parentnode/tree.c b/ext/dom/parentnode/tree.c index f57fd1cc7335b..c51bd2753cd8d 100644 --- a/ext/dom/parentnode/tree.c +++ b/ext/dom/parentnode/tree.c @@ -22,9 +22,34 @@ #include "php.h" #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "../php_dom.h" +#include "../obj_map.h" #include "../internal_helpers.h" #include "../dom_properties.h" +zval *dom_parent_node_children(dom_object *obj) +{ + return dom_get_prop_checked_offset(obj, 0, "children"); +} + +zend_result dom_parent_node_children_read(dom_object *obj, zval *retval) +{ + zval *cached_children = dom_parent_node_children(obj); + if (Z_ISUNDEF_P(cached_children)) { + object_init_ex(cached_children, dom_html_collection_class_entry); + php_dom_create_obj_map(obj, Z_DOMOBJ_P(cached_children), NULL, NULL, NULL, &php_dom_obj_map_child_elements); + + /* Handle cycles for potential TMPVARs (could also be CV but we can't differentiate). + * RC == 2 because of 1 TMPVAR and 1 in HTMLCollection. */ + if (GC_REFCOUNT(&obj->std) == 2) { + gc_possible_root(Z_COUNTED_P(cached_children)); + } + } + + ZVAL_OBJ_COPY(retval, Z_OBJ_P(cached_children)); + + return SUCCESS; +} + /* {{{ firstElementChild DomParentNode readonly=yes URL: https://www.w3.org/TR/dom/#dom-parentnode-firstelementchild diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 6e85ea887e4ec..ee99f97f35455 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -23,6 +23,7 @@ #include "php.h" #if defined(HAVE_LIBXML) && defined(HAVE_DOM) #include "zend_enum.h" +#include "zend_attributes.h" #include "php_dom.h" #include "obj_map.h" #include "nodelist.h" @@ -95,6 +96,7 @@ PHP_DOM_EXPORT zend_class_entry *dom_namespace_info_class_entry; static zend_object_handlers dom_object_handlers; static zend_object_handlers dom_nnodemap_object_handlers; static zend_object_handlers dom_nodelist_object_handlers; +static zend_object_handlers dom_unset_children_property_object_handlers; static zend_object_handlers dom_modern_nnodemap_object_handlers; static zend_object_handlers dom_modern_nodelist_object_handlers; static zend_object_handlers dom_html_collection_object_handlers; @@ -667,14 +669,35 @@ static zend_object *dom_objects_store_clone_obj(zend_object *zobject) /* {{{ */ static zend_object *dom_modern_element_clone_obj(zend_object *zobject) { zend_object *clone = dom_objects_store_clone_obj(zobject); + dom_object *intern = php_dom_obj_from_obj(clone); /* The $classList property is unique per element, and cached due to its [[SameObject]] requirement. * Remove it from the clone so the clone will get a fresh instance upon demand. */ - zval *class_list = dom_element_class_list_zval(php_dom_obj_from_obj(clone)); + zval *class_list = dom_element_class_list_zval(intern); if (!Z_ISUNDEF_P(class_list)) { zval_ptr_dtor(class_list); ZVAL_UNDEF(class_list); } + /* Likewise for $children */ + zval *children = dom_parent_node_children(intern); + if (!Z_ISUNDEF_P(children)) { + zval_ptr_dtor(children); + ZVAL_UNDEF(children); + } + + return clone; +} + +static zend_object *dom_clone_obj_unset_children_property(zend_object *zobject) +{ + zend_object *clone = dom_objects_store_clone_obj(zobject); + dom_object *intern = php_dom_obj_from_obj(clone); + + zval *children = dom_parent_node_children(intern); + if (!Z_ISUNDEF_P(children)) { + zval_ptr_dtor(children); + ZVAL_UNDEF(children); + } return clone; } @@ -776,10 +799,14 @@ PHP_MINIT_FUNCTION(dom) memcpy(&dom_modern_element_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); dom_modern_element_object_handlers.clone_obj = dom_modern_element_clone_obj; + memcpy(&dom_unset_children_property_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); + dom_unset_children_property_object_handlers.clone_obj = dom_clone_obj_unset_children_property; + memcpy(&dom_nnodemap_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); dom_nnodemap_object_handlers.free_obj = dom_nnodemap_objects_free_storage; dom_nnodemap_object_handlers.read_dimension = dom_nodemap_read_dimension; dom_nnodemap_object_handlers.has_dimension = dom_nodemap_has_dimension; + dom_nnodemap_object_handlers.clone_obj = NULL; memcpy(&dom_nodelist_object_handlers, &dom_nnodemap_object_handlers, sizeof(zend_object_handlers)); dom_nodelist_object_handlers.read_dimension = dom_nodelist_read_dimension; @@ -796,6 +823,7 @@ PHP_MINIT_FUNCTION(dom) memcpy(&dom_html_collection_object_handlers, &dom_modern_nodelist_object_handlers, sizeof(zend_object_handlers)); dom_html_collection_object_handlers.read_dimension = dom_html_collection_read_dimension; dom_html_collection_object_handlers.has_dimension = dom_html_collection_has_dimension; + dom_html_collection_object_handlers.get_gc = dom_html_collection_get_gc; memcpy(&dom_object_namespace_node_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); dom_object_namespace_node_handlers.offset = XtOffsetOf(dom_object_namespace_node, dom.std); @@ -910,9 +938,10 @@ PHP_MINIT_FUNCTION(dom) dom_modern_documentfragment_class_entry = register_class_Dom_DocumentFragment(dom_modern_node_class_entry, dom_modern_parentnode_class_entry); dom_modern_documentfragment_class_entry->create_object = dom_objects_new; - dom_modern_documentfragment_class_entry->default_object_handlers = &dom_object_handlers; + dom_modern_documentfragment_class_entry->default_object_handlers = &dom_unset_children_property_object_handlers; zend_hash_init(&dom_modern_documentfragment_prop_handlers, 0, NULL, NULL, true); + DOM_REGISTER_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "children", dom_parent_node_children_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_documentfragment_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL); @@ -921,7 +950,7 @@ PHP_MINIT_FUNCTION(dom) zend_hash_add_new_ptr(&classes, dom_modern_documentfragment_class_entry->name, &dom_modern_documentfragment_prop_handlers); dom_abstract_base_document_class_entry = register_class_Dom_Document(dom_modern_node_class_entry, dom_modern_parentnode_class_entry); - dom_abstract_base_document_class_entry->default_object_handlers = &dom_object_handlers; + dom_abstract_base_document_class_entry->default_object_handlers = &dom_unset_children_property_object_handlers; zend_hash_init(&dom_abstract_base_document_prop_handlers, 0, NULL, NULL, true); DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "implementation", dom_modern_document_implementation_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "URL", dom_document_document_uri_read, dom_document_document_uri_write); @@ -931,6 +960,7 @@ PHP_MINIT_FUNCTION(dom) DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "inputEncoding", dom_document_encoding_read, dom_html_document_encoding_write); DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "doctype", dom_document_doctype_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "documentElement", dom_document_document_element_read, NULL); + DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "children", dom_parent_node_children_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_abstract_base_document_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL); @@ -1117,6 +1147,7 @@ PHP_MINIT_FUNCTION(dom) DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "className", dom_element_class_name_read, dom_element_class_name_write); DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "classList", dom_element_class_list_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "attributes", dom_node_attributes_read, NULL); + DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "children", dom_parent_node_children_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "firstElementChild", dom_parent_node_first_element_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "lastElementChild", dom_parent_node_last_element_child_read, NULL); DOM_REGISTER_PROP_HANDLER(&dom_modern_element_prop_handlers, "childElementCount", dom_parent_node_child_element_count, NULL); @@ -1533,8 +1564,8 @@ void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */ dom_nnodemap_object *objmap = (dom_nnodemap_object *)intern->ptr; if (objmap) { - if (objmap->cached_obj && GC_DELREF(&objmap->cached_obj->std) == 0) { - zend_objects_store_del(&objmap->cached_obj->std); + if (objmap->cached_obj) { + OBJ_RELEASE(&objmap->cached_obj->std); } if (objmap->release_local) { dom_zend_string_release_from_char_pointer(objmap->local); @@ -2302,10 +2333,10 @@ void php_dom_get_content_into_zval(const xmlNode *nodep, zval *return_value, boo } case XML_ATTRIBUTE_NODE: { - bool free; - xmlChar *value = php_libxml_attr_value((const xmlAttr *) nodep, &free); + bool should_free; + xmlChar *value = php_libxml_attr_value((const xmlAttr *) nodep, &should_free); RETVAL_STRING_FAST((const char *) value); - if (free) { + if (should_free) { xmlFree(value); } return; @@ -2342,7 +2373,7 @@ static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int t zend_long lval; if (dom_nodemap_or_nodelist_process_offset_as_named(offset, &lval)) { /* exceptional case, switch to named lookup */ - php_dom_obj_map_get_named_item_into_zval(php_dom_obj_from_obj(object)->ptr, Z_STR_P(offset), NULL, rv); + php_dom_obj_map_get_ns_named_item_into_zval(php_dom_obj_from_obj(object)->ptr, Z_STR_P(offset), NULL, rv); return rv; } @@ -2368,7 +2399,7 @@ static int dom_nodemap_has_dimension(zend_object *object, zval *member, int chec if (dom_nodemap_or_nodelist_process_offset_as_named(member, &offset)) { /* exceptional case, switch to named lookup */ dom_nnodemap_object *map = php_dom_obj_from_obj(object)->ptr; - return map->handler->has_named_item(map, Z_STR_P(member), NULL); + return map->handler->has_ns_named_item(map, Z_STR_P(member), NULL); } return offset >= 0 && offset < php_dom_get_namednodemap_length(php_dom_obj_from_obj(object)); @@ -2389,7 +2420,7 @@ static zval *dom_modern_nodemap_read_dimension(zend_object *object, zval *offset if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), lval)) { map->handler->get_item(map, (zend_long) lval, rv); } else { - php_dom_obj_map_get_named_item_into_zval(map, Z_STR_P(offset), NULL, rv); + php_dom_obj_map_get_ns_named_item_into_zval(map, Z_STR_P(offset), NULL, rv); } } else if (Z_TYPE_P(offset) == IS_LONG) { map->handler->get_item(map, Z_LVAL_P(offset), rv); @@ -2417,7 +2448,7 @@ static int dom_modern_nodemap_has_dimension(zend_object *object, zval *member, i if (ZEND_HANDLE_NUMERIC(Z_STR_P(member), lval)) { return (zend_long) lval >= 0 && (zend_long) lval < php_dom_get_namednodemap_length(obj); } else { - return map->handler->has_named_item(map, Z_STR_P(member), NULL); + return map->handler->has_ns_named_item(map, Z_STR_P(member), NULL); } } else if (Z_TYPE_P(member) == IS_LONG) { zend_long offset = Z_LVAL_P(member); diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 0ff8692c4cc74..34cc4af85c568 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -160,7 +160,11 @@ bool php_dom_create_nullable_object(xmlNodePtr obj, zval *return_value, dom_obje xmlNodePtr dom_clone_node(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node, xmlDocPtr doc, bool recursive); void dom_set_document_ref_pointers(xmlNodePtr node, php_libxml_ref_obj *document); void dom_set_document_ref_pointers_attr(xmlAttrPtr attr, php_libxml_ref_obj *document); + +/* Prop getters by offset */ +zval *dom_get_prop_checked_offset(dom_object *obj, uint32_t offset, const char *name); zval *dom_element_class_list_zval(dom_object *obj); +zval *dom_parent_node_children(dom_object *obj); typedef enum { DOM_LOAD_STRING = 0, diff --git a/ext/dom/php_dom.stub.php b/ext/dom/php_dom.stub.php index 43d26ec7a3c7d..7236e80b4d247 100644 --- a/ext/dom/php_dom.stub.php +++ b/ext/dom/php_dom.stub.php @@ -147,9 +147,9 @@ /** * @var int - * @deprecated is no longer used since 8.4 * @cvalue PHP_ERR */ + #[\Deprecated(since: '8.4', message: 'as it is no longer used')] const DOM_PHP_ERR = UNKNOWN; /** * @var int @@ -1584,6 +1584,36 @@ class Element extends Node implements ParentNode, ChildNode */ public string $tagName; + /** + * @readonly + */ + public HTMLCollection $children; + /** + * @readonly + * @virtual + */ + public ?Element $firstElementChild; + /** + * @readonly + * @virtual + */ + public ?Element $lastElementChild; + /** + * @readonly + * @virtual + */ + public int $childElementCount; + /** + * @readonly + * @virtual + */ + public ?Element $previousElementSibling; + /** + * @readonly + * @virtual + */ + public ?Element $nextElementSibling; + /** @virtual */ public string $id; /** @virtual */ @@ -1629,37 +1659,12 @@ public function removeAttributeNode(Attr $attr) : Attr {} public function getElementsByTagName(string $qualifiedName): HTMLCollection {} public function getElementsByTagNameNS(?string $namespace, string $localName): HTMLCollection {} + public function getElementsByClassName(string $classNames): HTMLCollection {} public function insertAdjacentElement(AdjacentPosition $where, Element $element): ?Element {} public function insertAdjacentText(AdjacentPosition $where, string $data): void {} public function insertAdjacentHTML(AdjacentPosition $where, string $string): void {} - /** - * @readonly - * @virtual - */ - public ?Element $firstElementChild; - /** - * @readonly - * @virtual - */ - public ?Element $lastElementChild; - /** - * @readonly - * @virtual - */ - public int $childElementCount; - /** - * @readonly - * @virtual - */ - public ?Element $previousElementSibling; - /** - * @readonly - * @virtual - */ - public ?Element $nextElementSibling; - /** @implementation-alias DOMElement::setIdAttribute */ public function setIdAttribute(string $qualifiedName, bool $isId): void {} /** @implementation-alias DOMElement::setIdAttributeNS */ @@ -1863,6 +1868,10 @@ public function replaceWith(Node|string ...$nodes): void {} class DocumentFragment extends Node implements ParentNode { + /** + * @readonly + */ + public HTMLCollection $children; /** * @readonly * @virtual @@ -1931,6 +1940,26 @@ class Notation extends Node abstract class Document extends Node implements ParentNode { + /** + * @readonly + */ + public HTMLCollection $children; + /** + * @readonly + * @virtual + */ + public ?Element $firstElementChild; + /** + * @readonly + * @virtual + */ + public ?Element $lastElementChild; + /** + * @readonly + * @virtual + */ + public int $childElementCount; + /** @readonly */ public Implementation $implementation; /** @virtual */ @@ -1958,6 +1987,8 @@ abstract class Document extends Node implements ParentNode public function getElementsByTagName(string $qualifiedName): HTMLCollection {} /** @implementation-alias Dom\Element::getElementsByTagNameNS */ public function getElementsByTagNameNS(?string $namespace, string $localName): HTMLCollection {} + /** @implementation-alias Dom\Element::getElementsByClassName */ + public function getElementsByClassName(string $classNames): HTMLCollection {} public function createElement(string $localName): Element {} public function createElementNS(?string $namespace, string $qualifiedName): Element {} @@ -1979,22 +2010,6 @@ public function createAttribute(string $localName): Attr {} /** @implementation-alias DOMDocument::createAttributeNS */ public function createAttributeNS(?string $namespace, string $qualifiedName): Attr {} - /** - * @readonly - * @virtual - */ - public ?Element $firstElementChild; - /** - * @readonly - * @virtual - */ - public ?Element $lastElementChild; - /** - * @readonly - * @virtual - */ - public int $childElementCount; - /** @implementation-alias DOMDocument::getElementById */ public function getElementById(string $elementId): ?Element {} diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index 5c21b909b0e18..0eddfd96469fe 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0fcee2fa666dc88faf084578dde157409a6f5594 */ + * Stub hash: 757889c0ca89cc8e9905ba465e0621fe89b6e716 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_dom_import_simplexml, 0, 1, DOMAttr|DOMElement, 0) ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0) @@ -775,6 +775,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Dom_Element_getElementsByTa ZEND_ARG_TYPE_INFO(0, localName, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Dom_Element_getElementsByClassName, 0, 1, Dom\\HTMLCollection, 0) + ZEND_ARG_TYPE_INFO(0, classNames, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Dom_Element_insertAdjacentElement, 0, 2, Dom\\Element, 1) ZEND_ARG_OBJ_INFO(0, where, Dom\\AdjacentPosition, 0) ZEND_ARG_OBJ_INFO(0, element, Dom\\Element, 0) @@ -906,6 +910,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_Dom_Document_getElementsByTagNameNS arginfo_class_Dom_Element_getElementsByTagNameNS +#define arginfo_class_Dom_Document_getElementsByClassName arginfo_class_Dom_Element_getElementsByClassName + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Dom_Document_createElement, 0, 1, Dom\\Element, 0) ZEND_ARG_TYPE_INFO(0, localName, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -1278,6 +1284,7 @@ ZEND_METHOD(Dom_Element, setAttributeNodeNS); ZEND_METHOD(Dom_Element, removeAttributeNode); ZEND_METHOD(Dom_Element, getElementsByTagName); ZEND_METHOD(Dom_Element, getElementsByTagNameNS); +ZEND_METHOD(Dom_Element, getElementsByClassName); ZEND_METHOD(Dom_Element, insertAdjacentElement); ZEND_METHOD(Dom_Element, insertAdjacentText); ZEND_METHOD(Dom_Element, insertAdjacentHTML); @@ -1653,6 +1660,7 @@ static const zend_function_entry class_Dom_Element_methods[] = { ZEND_ME(Dom_Element, removeAttributeNode, arginfo_class_Dom_Element_removeAttributeNode, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Element, getElementsByTagName, arginfo_class_Dom_Element_getElementsByTagName, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Element, getElementsByTagNameNS, arginfo_class_Dom_Element_getElementsByTagNameNS, ZEND_ACC_PUBLIC) + ZEND_ME(Dom_Element, getElementsByClassName, arginfo_class_Dom_Element_getElementsByClassName, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Element, insertAdjacentElement, arginfo_class_Dom_Element_insertAdjacentElement, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Element, insertAdjacentText, arginfo_class_Dom_Element_insertAdjacentText, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Element, insertAdjacentHTML, arginfo_class_Dom_Element_insertAdjacentHTML, ZEND_ACC_PUBLIC) @@ -1721,6 +1729,7 @@ static const zend_function_entry class_Dom_DocumentFragment_methods[] = { static const zend_function_entry class_Dom_Document_methods[] = { ZEND_RAW_FENTRY("getElementsByTagName", zim_Dom_Element_getElementsByTagName, arginfo_class_Dom_Document_getElementsByTagName, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getElementsByTagNameNS", zim_Dom_Element_getElementsByTagNameNS, arginfo_class_Dom_Document_getElementsByTagNameNS, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("getElementsByClassName", zim_Dom_Element_getElementsByClassName, arginfo_class_Dom_Document_getElementsByClassName, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(Dom_Document, createElement, arginfo_class_Dom_Document_createElement, ZEND_ACC_PUBLIC) ZEND_ME(Dom_Document, createElementNS, arginfo_class_Dom_Document_createElementNS, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("createDocumentFragment", zim_DOMDocument_createDocumentFragment, arginfo_class_Dom_Document_createDocumentFragment, ZEND_ACC_PUBLIC, NULL, NULL) @@ -1837,7 +1846,7 @@ static void register_php_dom_symbols(int module_number) REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NMTOKENS", XML_ATTRIBUTE_NMTOKENS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ENUMERATION", XML_ATTRIBUTE_ENUMERATION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NOTATION", XML_ATTRIBUTE_NOTATION, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("DOM_PHP_ERR", PHP_ERR, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_DOM_PHP_ERR = REGISTER_LONG_CONSTANT("DOM_PHP_ERR", PHP_ERR, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("DOM_INDEX_SIZE_ERR", INDEX_SIZE_ERR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DOMSTRING_SIZE_ERR", DOMSTRING_SIZE_ERR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("DOM_HIERARCHY_REQUEST_ERR", HIERARCHY_REQUEST_ERR, CONST_PERSISTENT); @@ -1870,6 +1879,14 @@ static void register_php_dom_symbols(int module_number) REGISTER_LONG_CONSTANT("Dom\\NAMESPACE_ERR", NAMESPACE_ERR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Dom\\VALIDATION_ERR", VALIDATION_ERR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("Dom\\HTML_NO_DEFAULT_NS", DOM_HTML_NO_DEFAULT_NS, CONST_PERSISTENT); + + + zend_attribute *attribute_Deprecated_const_DOM_PHP_ERR_0 = zend_add_global_constant_attribute(const_DOM_PHP_ERR, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_DOM_PHP_ERR_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_DOM_PHP_ERR_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_DOM_PHP_ERR_0_arg1_str = zend_string_init("as it is no longer used", strlen("as it is no longer used"), 1); + ZVAL_STR(&attribute_Deprecated_const_DOM_PHP_ERR_0->args[1].value, attribute_Deprecated_const_DOM_PHP_ERR_0_arg1_str); + attribute_Deprecated_const_DOM_PHP_ERR_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_DOMDocumentType(zend_class_entry *class_entry_DOMNode) @@ -3011,31 +3028,12 @@ static zend_class_entry *register_class_Dom_Element(zend_class_entry *class_entr zend_declare_typed_property(class_entry, property_tagName_name, &property_tagName_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); zend_string_release(property_tagName_name); - zval property_id_default_value; - ZVAL_UNDEF(&property_id_default_value); - zend_string *property_id_name = zend_string_init("id", sizeof("id") - 1, 1); - zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_id_name); - - zval property_className_default_value; - ZVAL_UNDEF(&property_className_default_value); - zend_string *property_className_name = zend_string_init("className", sizeof("className") - 1, 1); - zend_declare_typed_property(class_entry, property_className_name, &property_className_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_className_name); - - zval property_classList_default_value; - ZVAL_UNDEF(&property_classList_default_value); - zend_string *property_classList_name = zend_string_init("classList", sizeof("classList") - 1, 1); - zend_string *property_classList_class_Dom_TokenList = zend_string_init("Dom\\TokenList", sizeof("Dom\\TokenList")-1, 1); - zend_declare_typed_property(class_entry, property_classList_name, &property_classList_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_classList_class_Dom_TokenList, 0, 0)); - zend_string_release(property_classList_name); - - zval property_attributes_default_value; - ZVAL_UNDEF(&property_attributes_default_value); - zend_string *property_attributes_name = zend_string_init("attributes", sizeof("attributes") - 1, 1); - zend_string *property_attributes_class_Dom_NamedNodeMap = zend_string_init("Dom\\\116amedNodeMap", sizeof("Dom\\\116amedNodeMap")-1, 1); - zend_declare_typed_property(class_entry, property_attributes_name, &property_attributes_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_attributes_class_Dom_NamedNodeMap, 0, 0)); - zend_string_release(property_attributes_name); + zval property_children_default_value; + ZVAL_UNDEF(&property_children_default_value); + zend_string *property_children_name = zend_string_init("children", sizeof("children") - 1, 1); + zend_string *property_children_class_Dom_HTMLCollection = zend_string_init("Dom\\HTMLCollection", sizeof("Dom\\HTMLCollection")-1, 1); + zend_declare_typed_property(class_entry, property_children_name, &property_children_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_children_class_Dom_HTMLCollection, 0, 0)); + zend_string_release(property_children_name); zval property_firstElementChild_default_value; ZVAL_UNDEF(&property_firstElementChild_default_value); @@ -3071,6 +3069,32 @@ static zend_class_entry *register_class_Dom_Element(zend_class_entry *class_entr zend_declare_typed_property(class_entry, property_nextElementSibling_name, &property_nextElementSibling_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_nextElementSibling_class_Dom_Element, 0, MAY_BE_NULL)); zend_string_release(property_nextElementSibling_name); + zval property_id_default_value; + ZVAL_UNDEF(&property_id_default_value); + zend_string *property_id_name = zend_string_init("id", sizeof("id") - 1, 1); + zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + zend_string_release(property_id_name); + + zval property_className_default_value; + ZVAL_UNDEF(&property_className_default_value); + zend_string *property_className_name = zend_string_init("className", sizeof("className") - 1, 1); + zend_declare_typed_property(class_entry, property_className_name, &property_className_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + zend_string_release(property_className_name); + + zval property_classList_default_value; + ZVAL_UNDEF(&property_classList_default_value); + zend_string *property_classList_name = zend_string_init("classList", sizeof("classList") - 1, 1); + zend_string *property_classList_class_Dom_TokenList = zend_string_init("Dom\\TokenList", sizeof("Dom\\TokenList")-1, 1); + zend_declare_typed_property(class_entry, property_classList_name, &property_classList_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_classList_class_Dom_TokenList, 0, 0)); + zend_string_release(property_classList_name); + + zval property_attributes_default_value; + ZVAL_UNDEF(&property_attributes_default_value); + zend_string *property_attributes_name = zend_string_init("attributes", sizeof("attributes") - 1, 1); + zend_string *property_attributes_class_Dom_NamedNodeMap = zend_string_init("Dom\\\116amedNodeMap", sizeof("Dom\\\116amedNodeMap")-1, 1); + zend_declare_typed_property(class_entry, property_attributes_name, &property_attributes_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_attributes_class_Dom_NamedNodeMap, 0, 0)); + zend_string_release(property_attributes_name); + zval property_innerHTML_default_value; ZVAL_UNDEF(&property_innerHTML_default_value); zend_string *property_innerHTML_name = zend_string_init("innerHTML", sizeof("innerHTML") - 1, 1); @@ -3295,6 +3319,13 @@ static zend_class_entry *register_class_Dom_DocumentFragment(zend_class_entry *c class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Dom_Node, 0); zend_class_implements(class_entry, 1, class_entry_Dom_ParentNode); + zval property_children_default_value; + ZVAL_UNDEF(&property_children_default_value); + zend_string *property_children_name = zend_string_init("children", sizeof("children") - 1, 1); + zend_string *property_children_class_Dom_HTMLCollection = zend_string_init("Dom\\HTMLCollection", sizeof("Dom\\HTMLCollection")-1, 1); + zend_declare_typed_property(class_entry, property_children_name, &property_children_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_children_class_Dom_HTMLCollection, 0, 0)); + zend_string_release(property_children_name); + zval property_firstElementChild_default_value; ZVAL_UNDEF(&property_firstElementChild_default_value); zend_string *property_firstElementChild_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, 1); @@ -3386,6 +3417,33 @@ static zend_class_entry *register_class_Dom_Document(zend_class_entry *class_ent class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Dom_Node, ZEND_ACC_ABSTRACT); zend_class_implements(class_entry, 1, class_entry_Dom_ParentNode); + zval property_children_default_value; + ZVAL_UNDEF(&property_children_default_value); + zend_string *property_children_name = zend_string_init("children", sizeof("children") - 1, 1); + zend_string *property_children_class_Dom_HTMLCollection = zend_string_init("Dom\\HTMLCollection", sizeof("Dom\\HTMLCollection")-1, 1); + zend_declare_typed_property(class_entry, property_children_name, &property_children_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_children_class_Dom_HTMLCollection, 0, 0)); + zend_string_release(property_children_name); + + zval property_firstElementChild_default_value; + ZVAL_UNDEF(&property_firstElementChild_default_value); + zend_string *property_firstElementChild_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, 1); + zend_string *property_firstElementChild_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); + zend_declare_typed_property(class_entry, property_firstElementChild_name, &property_firstElementChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_firstElementChild_class_Dom_Element, 0, MAY_BE_NULL)); + zend_string_release(property_firstElementChild_name); + + zval property_lastElementChild_default_value; + ZVAL_UNDEF(&property_lastElementChild_default_value); + zend_string *property_lastElementChild_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, 1); + zend_string *property_lastElementChild_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); + zend_declare_typed_property(class_entry, property_lastElementChild_name, &property_lastElementChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_lastElementChild_class_Dom_Element, 0, MAY_BE_NULL)); + zend_string_release(property_lastElementChild_name); + + zval property_childElementCount_default_value; + ZVAL_UNDEF(&property_childElementCount_default_value); + zend_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, 1); + zend_declare_typed_property(class_entry, property_childElementCount_name, &property_childElementCount_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(property_childElementCount_name); + zval property_implementation_default_value; ZVAL_UNDEF(&property_implementation_default_value); zend_string *property_implementation_name = zend_string_init("implementation", sizeof("implementation") - 1, 1); @@ -3437,26 +3495,6 @@ static zend_class_entry *register_class_Dom_Document(zend_class_entry *class_ent zend_declare_typed_property(class_entry, property_documentElement_name, &property_documentElement_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_documentElement_class_Dom_Element, 0, MAY_BE_NULL)); zend_string_release(property_documentElement_name); - zval property_firstElementChild_default_value; - ZVAL_UNDEF(&property_firstElementChild_default_value); - zend_string *property_firstElementChild_name = zend_string_init("firstElementChild", sizeof("firstElementChild") - 1, 1); - zend_string *property_firstElementChild_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); - zend_declare_typed_property(class_entry, property_firstElementChild_name, &property_firstElementChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_firstElementChild_class_Dom_Element, 0, MAY_BE_NULL)); - zend_string_release(property_firstElementChild_name); - - zval property_lastElementChild_default_value; - ZVAL_UNDEF(&property_lastElementChild_default_value); - zend_string *property_lastElementChild_name = zend_string_init("lastElementChild", sizeof("lastElementChild") - 1, 1); - zend_string *property_lastElementChild_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1); - zend_declare_typed_property(class_entry, property_lastElementChild_name, &property_lastElementChild_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_lastElementChild_class_Dom_Element, 0, MAY_BE_NULL)); - zend_string_release(property_lastElementChild_name); - - zval property_childElementCount_default_value; - ZVAL_UNDEF(&property_childElementCount_default_value); - zend_string *property_childElementCount_name = zend_string_init("childElementCount", sizeof("childElementCount") - 1, 1); - zend_declare_typed_property(class_entry, property_childElementCount_name, &property_childElementCount_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_childElementCount_name); - zval property_body_default_value; ZVAL_UNDEF(&property_body_default_value); zend_string *property_body_name = zend_string_init("body", sizeof("body") - 1, 1); diff --git a/ext/dom/tests/DOM_PHP_ERR_deprecated.phpt b/ext/dom/tests/DOM_PHP_ERR_deprecated.phpt index 76bd2757e7b5c..1dad517927206 100644 --- a/ext/dom/tests/DOM_PHP_ERR_deprecated.phpt +++ b/ext/dom/tests/DOM_PHP_ERR_deprecated.phpt @@ -7,5 +7,5 @@ dom var_dump(DOM_PHP_ERR); ?> --EXPECTF-- -Deprecated: Constant DOM_PHP_ERR is deprecated in %s on line %d +Deprecated: Constant DOM_PHP_ERR is deprecated since 8.4, as it is no longer used in %s on line %d int(0) diff --git a/ext/dom/tests/clone_list_map_collection.phpt b/ext/dom/tests/clone_list_map_collection.phpt new file mode 100644 index 0000000000000..1eb91c46069be --- /dev/null +++ b/ext/dom/tests/clone_list_map_collection.phpt @@ -0,0 +1,50 @@ +--TEST-- +Cloning node lists, maps, and collections should fail +--EXTENSIONS-- +dom +--FILE-- +loadXML(''); +try { + clone $dom->documentElement->attributes; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + clone $dom->documentElement->childNodes; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +$dom = Dom\XMLDocument::createFromString(']>'); +try { + clone $dom->documentElement->attributes; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + clone $dom->documentElement->childNodes; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + clone $dom->documentElement->children; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + clone $dom->doctype->entities; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Trying to clone an uncloneable object of class DOMNamedNodeMap +Trying to clone an uncloneable object of class DOMNodeList +Trying to clone an uncloneable object of class Dom\NamedNodeMap +Trying to clone an uncloneable object of class Dom\NodeList +Trying to clone an uncloneable object of class Dom\HTMLCollection +Trying to clone an uncloneable object of class Dom\DtdNamedNodeMap diff --git a/ext/dom/tests/gh15192.phpt b/ext/dom/tests/gh15192.phpt index c7bf0a543bb93..f6031c2a40b02 100644 --- a/ext/dom/tests/gh15192.phpt +++ b/ext/dom/tests/gh15192.phpt @@ -11,7 +11,7 @@ $dom = new DomDocument(); var_dump($element); ?> --EXPECT-- -object(Dom\HTMLElement)#3 (30) { +object(Dom\HTMLElement)#3 (31) { ["namespaceURI"]=> string(28) "http://www.w3.org/1999/xhtml" ["prefix"]=> @@ -28,6 +28,8 @@ object(Dom\HTMLElement)#3 (30) { string(22) "(object value omitted)" ["attributes"]=> string(22) "(object value omitted)" + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> string(22) "(object value omitted)" ["lastElementChild"]=> diff --git a/ext/dom/tests/gh16356.phpt b/ext/dom/tests/gh16356.phpt index ad09c2681806e..53d90d8490e29 100644 --- a/ext/dom/tests/gh16356.phpt +++ b/ext/dom/tests/gh16356.phpt @@ -13,7 +13,7 @@ var_dump($e1, $e2); ?> --EXPECT-- -object(Dom\Element)#3 (30) { +object(Dom\Element)#3 (31) { ["namespaceURI"]=> string(12) "urn:example1" ["prefix"]=> @@ -30,6 +30,8 @@ object(Dom\Element)#3 (30) { string(22) "(object value omitted)" ["attributes"]=> string(22) "(object value omitted)" + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> NULL ["lastElementChild"]=> @@ -75,7 +77,7 @@ object(Dom\Element)#3 (30) { ["textContent"]=> string(0) "" } -object(Dom\Element)#4 (30) { +object(Dom\Element)#4 (31) { ["namespaceURI"]=> string(12) "urn:example2" ["prefix"]=> @@ -92,6 +94,8 @@ object(Dom\Element)#4 (30) { string(22) "(object value omitted)" ["attributes"]=> string(22) "(object value omitted)" + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> NULL ["lastElementChild"]=> diff --git a/ext/dom/tests/gh19612.phpt b/ext/dom/tests/gh19612.phpt new file mode 100644 index 0000000000000..38554f3c83605 --- /dev/null +++ b/ext/dom/tests/gh19612.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-19612 (Mitigate libxml2 tree dictionary bug) +--EXTENSIONS-- +dom +--FILE-- +loadXML(<< +]> + +XML); +$html = new DOMDocument; +$html->loadHTML('

foo

', LIBXML_NOERROR); +$p = $html->documentElement->firstChild->firstChild; +$p->appendChild($html->adoptNode($xml->documentElement->firstElementChild->cloneNode(true))); + +echo $html->saveXML(); +echo $xml->saveXML(); +?> +--EXPECT-- + + +

foo

+ + +]> + diff --git a/ext/dom/tests/gh8996.phpt b/ext/dom/tests/gh8996.phpt index 62b7955bacf11..0706f2ecdecc3 100644 --- a/ext/dom/tests/gh8996.phpt +++ b/ext/dom/tests/gh8996.phpt @@ -80,6 +80,9 @@ echo "Serialized:\n-----------\n$serialized\n-----------\nRestored:\n----------- ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d === __sleep and __wakeup === string(144) "O:34:"SerializableDomDocumentSleepWakeup":1:{s:43:"%0SerializableDomDocumentSleepWakeup%0xmlData";s:39:" value diff --git a/ext/dom/tests/modern/common/Element_getElementsByClassName_empty.phpt b/ext/dom/tests/modern/common/Element_getElementsByClassName_empty.phpt new file mode 100644 index 0000000000000..d2e3b0ea22b9b --- /dev/null +++ b/ext/dom/tests/modern/common/Element_getElementsByClassName_empty.phpt @@ -0,0 +1,32 @@ +--TEST-- +Dom\Element::getElementsByClassName() empty class names +--EXTENSIONS-- +dom +--FILE-- + +

+ +HTML, LIBXML_NOERROR); + +$collection = $dom->documentElement->getElementsByClassName(""); +var_dump($collection->count()); + +foreach ($collection as $node) { + throw new Error("unreachable"); +} + +var_dump($dom->getElementsByClassName(" ")->count()); +var_dump($dom->getElementsByClassName("\t")->count()); +var_dump($dom->getElementsByClassName("\t\n\f\v")->count()); +var_dump($dom->getElementsByClassName("\t\n\f\v")->namedItem("child")); + +?> +--EXPECT-- +int(0) +int(0) +int(0) +int(0) +NULL diff --git a/ext/dom/tests/modern/common/Element_getElementsByClassName_non_quirks.phpt b/ext/dom/tests/modern/common/Element_getElementsByClassName_non_quirks.phpt new file mode 100644 index 0000000000000..e658e3399ca0d --- /dev/null +++ b/ext/dom/tests/modern/common/Element_getElementsByClassName_non_quirks.phpt @@ -0,0 +1,55 @@ +--TEST-- +Dom\Element::getElementsByClassName() non quirks mode +--EXTENSIONS-- +dom +--FILE-- + +
+

1

+

2

+

3

+

4

+

5

+

6

+
+
+

7

+

8

+

9

+

10

+

11

+
+HTML); + +$collection = $dom->getElementsByClassName("foo \n bar"); + +echo "There are {$collection->length} items in the document in total that have both \"foo\" and \"bar\"\n"; + +$collection = $dom->getElementById('container')->getElementsByClassName("foo \n bar"); + +echo "There are {$collection->length} items in #container in total that have both \"foo\" and \"bar\"\n"; + +foreach ($collection as $key => $node) { + echo "--- Key $key ---\n"; + var_dump($node->tagName, $node->textContent); + var_dump($node === $collection->item($key)); +} + +var_dump($collection->namedItem("here")->textContent); + +?> +--EXPECT-- +There are 3 items in the document in total that have both "foo" and "bar" +There are 2 items in #container in total that have both "foo" and "bar" +--- Key 0 --- +string(1) "P" +string(1) "5" +bool(true) +--- Key 1 --- +string(1) "P" +string(1) "6" +bool(true) +string(1) "6" diff --git a/ext/dom/tests/modern/common/Element_getElementsByClassName_quirks.phpt b/ext/dom/tests/modern/common/Element_getElementsByClassName_quirks.phpt new file mode 100644 index 0000000000000..52e964ea43177 --- /dev/null +++ b/ext/dom/tests/modern/common/Element_getElementsByClassName_quirks.phpt @@ -0,0 +1,69 @@ +--TEST-- +Dom\Element::getElementsByClassName() quirks mode +--EXTENSIONS-- +dom +--FILE-- + +
+

1

+

2

+

3

+

4

+
+ + +HTML, LIBXML_NOERROR); +$collection = $dom->documentElement->getElementsByClassName("Bar"); + +echo "There are {$dom->getElementsByClassName("foo \n bar")->count()} items in the document in total that have both \"foo\" and \"bar\"\n"; + +echo "There are {$collection->count()} \"Bar\" items\n"; + +foreach ($collection as $key => $node) { + echo "--- Key $key ---\n"; + var_dump($node->tagName, $node->textContent); + var_dump($node === $collection->item($key)); +} + +echo "--- named item \"here\" ---\n"; + +var_dump($collection->namedItem("here")->textContent); + +?> +--EXPECT-- +There are 1 items in the document in total that have both "foo" and "bar" +There are 4 "Bar" items +--- Key 0 --- +string(3) "DIV" +string(56) " + + 1 + 2 + 3 + 4 + + +" +bool(true) +--- Key 1 --- +string(4) "MAIN" +string(45) " + 1 + 2 + 3 + 4 + " +bool(true) +--- Key 2 --- +string(1) "P" +string(1) "2" +bool(true) +--- Key 3 --- +string(1) "P" +string(1) "4" +bool(true) +--- named item "here" --- +string(1) "2" diff --git a/ext/dom/tests/modern/common/ParentNode_children.phpt b/ext/dom/tests/modern/common/ParentNode_children.phpt new file mode 100644 index 0000000000000..54db132f1b161 --- /dev/null +++ b/ext/dom/tests/modern/common/ParentNode_children.phpt @@ -0,0 +1,48 @@ +--TEST-- +ParentNode::$children +--EXTENSIONS-- +dom +--FILE-- + +
+ + + + + +XML); +$children = $dom->documentElement->children; +var_dump($children === $dom->documentElement->children); // Tests caching behaviour +var_dump($children !== (clone $dom->documentElement)->children); // Tests caching behaviour does not persist across clones +var_dump(count($children)); +var_dump($children->length); + +foreach ($children as $key => $child) { + var_dump($key, $child->nodeName); +} + +foreach ($children->namedItem('foo')->children as $key => $child) { + var_dump($key, $child->nodeName); +} + +?> +--EXPECT-- +bool(true) +bool(true) +int(4) +int(4) +int(0) +string(1) "a" +int(1) +string(1) "b" +int(2) +string(1) "c" +int(3) +string(1) "e" +int(0) +string(2) "c1" +int(1) +string(2) "c2" diff --git a/ext/dom/tests/modern/css_selectors/gh18877.phpt b/ext/dom/tests/modern/css_selectors/gh18877.phpt new file mode 100644 index 0000000000000..8cab491a0ddeb --- /dev/null +++ b/ext/dom/tests/modern/css_selectors/gh18877.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-18877 (\Dom\HTMLDocument querySelectorAll selecting only the first when using ~ and :has) +--EXTENSIONS-- +dom +--FILE-- + + + + +
+ 1 + 2 + 3 + + +TEXT; + +$dom = \Dom\HTMLDocument::createFromString($text, options: LIBXML_NOERROR); +foreach ($dom->querySelectorAll('div:has(div) ~ *') as $node) { + var_dump($node->textContent); +} + +?> +--EXPECT-- +string(1) "1" +string(1) "2" +string(1) "3" diff --git a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt index 5051c3f9aabf6..c6347ae485894 100644 --- a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt +++ b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_01.phpt @@ -23,7 +23,7 @@ var_dump(get_class($dom->getElementsByTagName("p")->item(0))); ?> --EXPECT-- -object(Dom\HTMLDocument)#1 (28) { +object(Dom\HTMLDocument)#1 (29) { ["implementation"]=> string(22) "(object value omitted)" ["URL"]=> @@ -40,6 +40,8 @@ object(Dom\HTMLDocument)#1 (28) { NULL ["documentElement"]=> string(22) "(object value omitted)" + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> string(22) "(object value omitted)" ["lastElementChild"]=> diff --git a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt index b160c72f0a54f..d7dea308b5d2a 100644 --- a/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt +++ b/ext/dom/tests/modern/html/interactions/HTMLDocument_should_retain_properties_and_owner_02.phpt @@ -23,7 +23,7 @@ var_dump(get_class($dom->getElementsByTagName("p")->item(0))); ?> --EXPECT-- -object(Dom\HTMLDocument)#1 (28) { +object(Dom\HTMLDocument)#1 (29) { ["implementation"]=> string(22) "(object value omitted)" ["URL"]=> @@ -40,6 +40,8 @@ object(Dom\HTMLDocument)#1 (28) { NULL ["documentElement"]=> string(22) "(object value omitted)" + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> string(22) "(object value omitted)" ["lastElementChild"]=> diff --git a/ext/dom/tests/modern/spec/Document_implementation_createDocument.phpt b/ext/dom/tests/modern/spec/Document_implementation_createDocument.phpt index ae49a6a494c9a..4cf1b3888feed 100644 --- a/ext/dom/tests/modern/spec/Document_implementation_createDocument.phpt +++ b/ext/dom/tests/modern/spec/Document_implementation_createDocument.phpt @@ -37,7 +37,7 @@ echo $dom->implementation->createDocument(null, "", $dtd)->saveXml(), "\n"; ?> --EXPECT-- --- (null, "") --- -object(Dom\XMLDocument)#3 (32) { +object(Dom\XMLDocument)#3 (33) { ["xmlEncoding"]=> string(5) "UTF-8" ["xmlStandalone"]=> @@ -62,6 +62,8 @@ object(Dom\XMLDocument)#3 (32) { NULL ["documentElement"]=> NULL + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> NULL ["lastElementChild"]=> diff --git a/ext/dom/tests/modern/spec/ParentNode_append_exception_consistency.phpt b/ext/dom/tests/modern/spec/ParentNode_append_exception_consistency.phpt index 67a964a7ec515..a88b4fc808b08 100644 --- a/ext/dom/tests/modern/spec/ParentNode_append_exception_consistency.phpt +++ b/ext/dom/tests/modern/spec/ParentNode_append_exception_consistency.phpt @@ -18,7 +18,9 @@ var_dump($element->parentNode); ?> --EXPECT-- Exception: Cannot have more than one element child in a document -object(Dom\DocumentFragment)#2 (17) { +object(Dom\DocumentFragment)#2 (18) { + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> string(22) "(object value omitted)" ["lastElementChild"]=> diff --git a/ext/dom/tests/modern/xml/XMLDocument_debug.phpt b/ext/dom/tests/modern/xml/XMLDocument_debug.phpt index e2d6ebffe89cd..7067e5607bdb6 100644 --- a/ext/dom/tests/modern/xml/XMLDocument_debug.phpt +++ b/ext/dom/tests/modern/xml/XMLDocument_debug.phpt @@ -10,7 +10,7 @@ var_dump($dom); ?> --EXPECT-- -object(Dom\XMLDocument)#1 (32) { +object(Dom\XMLDocument)#1 (33) { ["xmlEncoding"]=> string(5) "UTF-8" ["xmlStandalone"]=> @@ -35,6 +35,8 @@ object(Dom\XMLDocument)#1 (32) { NULL ["documentElement"]=> NULL + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> NULL ["lastElementChild"]=> diff --git a/ext/dom/tests/modern/xml/XMLDocument_fromEmptyDocument_02.phpt b/ext/dom/tests/modern/xml/XMLDocument_fromEmptyDocument_02.phpt index 62d64a05f9b2a..6276d1e9a98cb 100644 --- a/ext/dom/tests/modern/xml/XMLDocument_fromEmptyDocument_02.phpt +++ b/ext/dom/tests/modern/xml/XMLDocument_fromEmptyDocument_02.phpt @@ -10,7 +10,7 @@ var_dump($dom); ?> --EXPECT-- -object(Dom\XMLDocument)#1 (32) { +object(Dom\XMLDocument)#1 (33) { ["xmlEncoding"]=> string(5) "UTF-8" ["xmlStandalone"]=> @@ -35,6 +35,8 @@ object(Dom\XMLDocument)#1 (32) { NULL ["documentElement"]=> NULL + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> NULL ["lastElementChild"]=> diff --git a/ext/dom/tests/modern/xml/XMLDocument_node_ownerDocument_for_XML.phpt b/ext/dom/tests/modern/xml/XMLDocument_node_ownerDocument_for_XML.phpt index e18c43f05ae82..89cfe83de710f 100644 --- a/ext/dom/tests/modern/xml/XMLDocument_node_ownerDocument_for_XML.phpt +++ b/ext/dom/tests/modern/xml/XMLDocument_node_ownerDocument_for_XML.phpt @@ -13,7 +13,7 @@ var_dump($element->ownerDocument); ?> --EXPECTF-- -object(Dom\XMLDocument)#1 (32) { +object(Dom\XMLDocument)#1 (33) { ["xmlEncoding"]=> string(5) "UTF-8" ["xmlStandalone"]=> @@ -38,6 +38,8 @@ object(Dom\XMLDocument)#1 (32) { NULL ["documentElement"]=> string(22) "(object value omitted)" + ["children"]=> + string(22) "(object value omitted)" ["firstElementChild"]=> string(22) "(object value omitted)" ["lastElementChild"]=> diff --git a/ext/dom/tests/modern/xml/gh18979.phpt b/ext/dom/tests/modern/xml/gh18979.phpt new file mode 100644 index 0000000000000..3a90bd583773b --- /dev/null +++ b/ext/dom/tests/modern/xml/gh18979.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-18979 (DOM\XMLDocument::createComment() triggers undefined behavior with null byte) +--EXTENSIONS-- +dom +--FILE-- +createElement("container"); +$container->append($dom->createComment("\0")); +var_dump($container->innerHTML); +?> +--EXPECT-- +string(7) "" diff --git a/ext/dom/token_list.c b/ext/dom/token_list.c index fe768e17b2e9c..84a3dc10afebc 100644 --- a/ext/dom/token_list.c +++ b/ext/dom/token_list.c @@ -51,7 +51,7 @@ static zend_always_inline void dom_add_token(HashTable *ht, zend_string *token) /* https://dom.spec.whatwg.org/#concept-ordered-set-parser * and https://infra.spec.whatwg.org/#split-on-ascii-whitespace */ -static void dom_ordered_set_parser(HashTable *token_set, const char *position) +void dom_ordered_set_parser(HashTable *token_set, const char *position, bool to_lowercase) { /* Adapted steps from "split on ASCII whitespace" such that that loop directly appends to the token set. */ @@ -72,6 +72,9 @@ static void dom_ordered_set_parser(HashTable *token_set, const char *position) /* 4.2. Append token to tokens. */ zend_string *token = zend_string_init(start, length, false); + if (to_lowercase) { + zend_str_tolower(ZSTR_VAL(token), length); + } dom_add_token(token_set, token); zend_string_release_ex(token, false); @@ -83,6 +86,53 @@ static void dom_ordered_set_parser(HashTable *token_set, const char *position) * => That's the token set. */ } +/* This returns true if all tokens in "token_set" are found in "value". */ +bool dom_ordered_set_all_contained(HashTable *token_set, const char *value, bool to_lowercase) +{ + /* This code is conceptually close to dom_ordered_set_parser(), + * but without building a hash table. + * Since the storage of the token set maps a value on itself, + * we can reuse that storage as a "seen" flag by setting it to NULL. */ + zval *zv; + + uint32_t still_needed = zend_hash_num_elements(token_set); + + value += strspn(value, ascii_whitespace); + + while (*value != '\0' && still_needed > 0) { + const char *start = value; + value += strcspn(value, ascii_whitespace); + size_t length = value - start; + + if (to_lowercase) { + ALLOCA_FLAG(use_heap) + char *lc_str = zend_str_tolower_copy(do_alloca(length + 1, use_heap), start, length); + zv = zend_hash_str_find(token_set, lc_str, length); + free_alloca(lc_str, use_heap); + } else { + zv = zend_hash_str_find(token_set, start, length); + } + if (zv) { + if (Z_STR_P(zv)) { + still_needed--; + Z_STR_P(zv) = NULL; + } + } + + value += strspn(value, ascii_whitespace); + } + + /* Restore "seen" flag. */ + zend_string *k; + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(token_set, k, zv) { + if (!Z_STR_P(zv)) { + Z_STR_P(zv) = k; + } + } ZEND_HASH_FOREACH_END(); + + return still_needed == 0; +} + /* https://dom.spec.whatwg.org/#concept-ordered-set-serializer */ static char *dom_ordered_set_serializer(HashTable *token_set) { @@ -166,7 +216,7 @@ static void dom_token_list_update_set(dom_token_list_object *intern, HashTable * xmlChar *value = dom_token_list_get_class_value(attr, &should_free); if (value != NULL) { /* 2. Otherwise, parse the token set. */ - dom_ordered_set_parser(token_set, (const char *) value); + dom_ordered_set_parser(token_set, (const char *) value, false); intern->cached_string = estrdup((const char *) value); } else { intern->cached_string = NULL; diff --git a/ext/dom/token_list.h b/ext/dom/token_list.h index 4711852c4d876..7c8a6f612ffa4 100644 --- a/ext/dom/token_list.h +++ b/ext/dom/token_list.h @@ -35,6 +35,8 @@ static inline dom_token_list_object *php_dom_token_list_from_dom_obj(dom_object return (dom_token_list_object *)((char *) obj - XtOffsetOf(dom_token_list_object, dom)); } +void dom_ordered_set_parser(HashTable *token_set, const char *position, bool to_lowercase); +bool dom_ordered_set_all_contained(HashTable *token_set, const char *value, bool to_lowercase); void dom_token_list_ctor(dom_token_list_object *intern, dom_object *element_obj); void dom_token_list_free_obj(zend_object *object); zval *dom_token_list_read_dimension(zend_object *object, zval *offset, int type, zval *rv); diff --git a/ext/dom/xml_serializer.c b/ext/dom/xml_serializer.c index debbb41fdadeb..a4b46082b0ee5 100644 --- a/ext/dom/xml_serializer.c +++ b/ext/dom/xml_serializer.c @@ -640,7 +640,11 @@ static int dom_xml_serialize_comment_node(xmlOutputBufferPtr out, xmlNodePtr com const xmlChar *ptr = comment->content; if (ptr != NULL) { TRY(dom_xml_check_char_production(ptr)); - if (strstr((const char *) ptr, "--") != NULL || ptr[strlen((const char *) ptr) - 1] == '-') { + if (strstr((const char *) ptr, "--") != NULL) { + return -1; + } + size_t len = strlen((const char *) ptr); + if (len > 0 && ptr[len - 1] == '-') { return -1; } } diff --git a/ext/enchant/enchant.stub.php b/ext/enchant/enchant.stub.php index eafce22eac7d3..6ddbee768f14d 100644 --- a/ext/enchant/enchant.stub.php +++ b/ext/enchant/enchant.stub.php @@ -5,14 +5,14 @@ /** * @var int * @cvalue PHP_ENCHANT_MYSPELL - * @deprecated */ +#[\Deprecated(since: '8.0', message: 'as enchant_broker_get_dict_path() and enchant_broker_set_dict_path() are deprecated')] const ENCHANT_MYSPELL = UNKNOWN; /** * @var int * @cvalue PHP_ENCHANT_ISPELL - * @deprecated */ +#[\Deprecated(since: '8.0', message: 'as enchant_broker_get_dict_path() and enchant_broker_set_dict_path() are deprecated')] const ENCHANT_ISPELL = UNKNOWN; #ifdef HAVE_ENCHANT_GET_VERSION /** diff --git a/ext/enchant/enchant_arginfo.h b/ext/enchant/enchant_arginfo.h index a06f713f9cedf..01681072346a0 100644 --- a/ext/enchant/enchant_arginfo.h +++ b/ext/enchant/enchant_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 9dd3fce23840ced1c265f8ec1dd3929298fdfe37 */ + * Stub hash: 31974eb901477da53ede7476953d461d32f772ba */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_enchant_broker_init, 0, 0, EnchantBroker, MAY_BE_FALSE) ZEND_END_ARG_INFO() @@ -156,74 +156,61 @@ static const zend_function_entry ext_functions[] = { static void register_enchant_symbols(int module_number) { - REGISTER_LONG_CONSTANT("ENCHANT_MYSPELL", PHP_ENCHANT_MYSPELL, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("ENCHANT_ISPELL", PHP_ENCHANT_ISPELL, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_ENCHANT_MYSPELL = REGISTER_LONG_CONSTANT("ENCHANT_MYSPELL", PHP_ENCHANT_MYSPELL, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_ENCHANT_ISPELL = REGISTER_LONG_CONSTANT("ENCHANT_ISPELL", PHP_ENCHANT_ISPELL, CONST_PERSISTENT | CONST_DEPRECATED); #if defined(HAVE_ENCHANT_GET_VERSION) REGISTER_STRING_CONSTANT("LIBENCHANT_VERSION", PHP_ENCHANT_GET_VERSION, CONST_PERSISTENT); #endif zend_attribute *attribute_Deprecated_func_enchant_broker_free_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "enchant_broker_free", sizeof("enchant_broker_free") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_enchant_broker_free_0_arg0; - zend_string *attribute_Deprecated_func_enchant_broker_free_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_0_arg0, attribute_Deprecated_func_enchant_broker_free_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_broker_free_0->args[0].value, &attribute_Deprecated_func_enchant_broker_free_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_enchant_broker_free_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_enchant_broker_free_0_arg1; zend_string *attribute_Deprecated_func_enchant_broker_free_0_arg1_str = zend_string_init("as EnchantBroker objects are freed automatically", strlen("as EnchantBroker objects are freed automatically"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_0_arg1, attribute_Deprecated_func_enchant_broker_free_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_broker_free_0->args[1].value, &attribute_Deprecated_func_enchant_broker_free_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_0->args[1].value, attribute_Deprecated_func_enchant_broker_free_0_arg1_str); attribute_Deprecated_func_enchant_broker_free_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_enchant_broker_set_dict_path_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "enchant_broker_set_dict_path", sizeof("enchant_broker_set_dict_path") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_enchant_broker_set_dict_path_0_arg0; - zend_string *attribute_Deprecated_func_enchant_broker_set_dict_path_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_broker_set_dict_path_0_arg0, attribute_Deprecated_func_enchant_broker_set_dict_path_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_broker_set_dict_path_0->args[0].value, &attribute_Deprecated_func_enchant_broker_set_dict_path_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_enchant_broker_set_dict_path_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_enchant_broker_set_dict_path_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_enchant_broker_get_dict_path_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "enchant_broker_get_dict_path", sizeof("enchant_broker_get_dict_path") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_enchant_broker_get_dict_path_0_arg0; - zend_string *attribute_Deprecated_func_enchant_broker_get_dict_path_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_broker_get_dict_path_0_arg0, attribute_Deprecated_func_enchant_broker_get_dict_path_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_broker_get_dict_path_0->args[0].value, &attribute_Deprecated_func_enchant_broker_get_dict_path_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_enchant_broker_get_dict_path_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_enchant_broker_get_dict_path_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_enchant_broker_free_dict_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "enchant_broker_free_dict", sizeof("enchant_broker_free_dict") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_enchant_broker_free_dict_0_arg0; - zend_string *attribute_Deprecated_func_enchant_broker_free_dict_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_dict_0_arg0, attribute_Deprecated_func_enchant_broker_free_dict_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_broker_free_dict_0->args[0].value, &attribute_Deprecated_func_enchant_broker_free_dict_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_dict_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_enchant_broker_free_dict_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_enchant_broker_free_dict_0_arg1; zend_string *attribute_Deprecated_func_enchant_broker_free_dict_0_arg1_str = zend_string_init("as EnchantDictionary objects are freed automatically", strlen("as EnchantDictionary objects are freed automatically"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_dict_0_arg1, attribute_Deprecated_func_enchant_broker_free_dict_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_broker_free_dict_0->args[1].value, &attribute_Deprecated_func_enchant_broker_free_dict_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_enchant_broker_free_dict_0->args[1].value, attribute_Deprecated_func_enchant_broker_free_dict_0_arg1_str); attribute_Deprecated_func_enchant_broker_free_dict_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_enchant_dict_add_to_personal_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "enchant_dict_add_to_personal", sizeof("enchant_dict_add_to_personal") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg0; - zend_string *attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg0, attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_dict_add_to_personal_0->args[0].value, &attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_enchant_dict_add_to_personal_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_enchant_dict_add_to_personal_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg1; zend_string *attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg1_str = zend_string_init("use enchant_dict_add() instead", strlen("use enchant_dict_add() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg1, attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_dict_add_to_personal_0->args[1].value, &attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_enchant_dict_add_to_personal_0->args[1].value, attribute_Deprecated_func_enchant_dict_add_to_personal_0_arg1_str); attribute_Deprecated_func_enchant_dict_add_to_personal_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_enchant_dict_is_in_session_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "enchant_dict_is_in_session", sizeof("enchant_dict_is_in_session") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_enchant_dict_is_in_session_0_arg0; - zend_string *attribute_Deprecated_func_enchant_dict_is_in_session_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_dict_is_in_session_0_arg0, attribute_Deprecated_func_enchant_dict_is_in_session_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_dict_is_in_session_0->args[0].value, &attribute_Deprecated_func_enchant_dict_is_in_session_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_enchant_dict_is_in_session_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_enchant_dict_is_in_session_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_enchant_dict_is_in_session_0_arg1; zend_string *attribute_Deprecated_func_enchant_dict_is_in_session_0_arg1_str = zend_string_init("use enchant_dict_is_added() instead", strlen("use enchant_dict_is_added() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_enchant_dict_is_in_session_0_arg1, attribute_Deprecated_func_enchant_dict_is_in_session_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_enchant_dict_is_in_session_0->args[1].value, &attribute_Deprecated_func_enchant_dict_is_in_session_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_enchant_dict_is_in_session_0->args[1].value, attribute_Deprecated_func_enchant_dict_is_in_session_0_arg1_str); attribute_Deprecated_func_enchant_dict_is_in_session_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_ENCHANT_MYSPELL_0 = zend_add_global_constant_attribute(const_ENCHANT_MYSPELL, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_ENCHANT_MYSPELL_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); + attribute_Deprecated_const_ENCHANT_MYSPELL_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_ENCHANT_MYSPELL_0_arg1_str = zend_string_init("as enchant_broker_get_dict_path() and enchant_broker_set_dict_path() are deprecated", strlen("as enchant_broker_get_dict_path() and enchant_broker_set_dict_path() are deprecated"), 1); + ZVAL_STR(&attribute_Deprecated_const_ENCHANT_MYSPELL_0->args[1].value, attribute_Deprecated_const_ENCHANT_MYSPELL_0_arg1_str); + attribute_Deprecated_const_ENCHANT_MYSPELL_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_ENCHANT_ISPELL_0 = zend_add_global_constant_attribute(const_ENCHANT_ISPELL, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_ENCHANT_ISPELL_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); + attribute_Deprecated_const_ENCHANT_ISPELL_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_ENCHANT_ISPELL_0->args[1].value, attribute_Deprecated_const_ENCHANT_MYSPELL_0_arg1_str); + attribute_Deprecated_const_ENCHANT_ISPELL_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_EnchantBroker(void) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 9169861728869..d0ca7a6819bd9 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -1290,6 +1290,18 @@ typedef struct { mn_offset_mode_t offset_mode; } maker_note_type; +#define FOURCC(id) (((uint32_t)(id[0])<<24) | (id[1]<<16) | (id[2]<<8) | (id[3])) + +typedef struct { + uint64_t size; + uint32_t type; +} isobmff_box_type; + +typedef struct { + uint32_t offset; + uint32_t size; +} isobmff_item_pos_type; + /* Some maker notes (e.g. DJI info tag) require custom parsing */ #define REQUIRES_CUSTOM_PARSING NULL @@ -4279,11 +4291,167 @@ static bool exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offs return result; } +/* Returns the size of the header, which must be smaller than the size of the box. */ +static int exif_isobmff_parse_box(unsigned char *buf, isobmff_box_type *box) +{ + box->size = php_ifd_get32u(buf, 1); + buf += 4; + box->type = php_ifd_get32u(buf, 1); + if (box->size != 1) { + return 8; + } + buf += 4; + box->size = php_ifd_get64u(buf, 1); + return 16; +} + +static void exif_isobmff_parse_meta(unsigned char *data, unsigned char *end, isobmff_item_pos_type *pos) +{ + isobmff_box_type box, item; + unsigned char *p; + int header_size, exif_id = -1, version, item_count, i; + + size_t remain; +#define CHECK(n) do { \ + if (remain < (n)) { \ + return; \ + } \ +} while (0) +#define ADVANCE(n) do { \ + CHECK(n); \ + remain -= (n); \ + p += (n); \ +} while (0) + + unsigned char *box_offset = data + 4; + while (box_offset < end - 16) { + header_size = exif_isobmff_parse_box(box_offset, &box); + if (box.size < header_size) { + return; + } + p = box_offset; + remain = end - p; + + if (box.type == FOURCC("iinf")) { + ADVANCE(header_size + 4); + version = p[-4]; + if (version < 2) { + ADVANCE(2); + item_count = php_ifd_get16u(p - 2, 1); + } else { + ADVANCE(4); + item_count = php_ifd_get32u(p - 4, 1); + } + for (i = 0; i < item_count && p < end - 20; i++) { + header_size = exif_isobmff_parse_box(p, &item); + if (item.size < header_size) { + return; + } + CHECK(header_size + 12); + if (!memcmp(p + header_size + 8, "Exif", 4)) { + exif_id = php_ifd_get16u(p + header_size + 4, 1); + break; + } + ADVANCE(item.size); + } + if (exif_id < 0) { + break; + } + } + else if (box.type == FOURCC("iloc")) { + ADVANCE(header_size + 6); + version = p[-6]; + if (version < 2) { + ADVANCE(2); + item_count = php_ifd_get16u(p - 2, 1); + } else { + ADVANCE(4); + item_count = php_ifd_get32u(p - 4, 1); + } + for (i = 0; i < item_count && p < end - 16; i++, p += 16) { + if (php_ifd_get16u(p, 1) == exif_id) { + pos->offset = php_ifd_get32u(p + 8, 1); + pos->size = php_ifd_get32u(p + 12, 1); + break; + } + } + break; + } + + if (end - 16 - box_offset <= box.size) { + break; + } + box_offset += box.size; + } + +#undef ADVANCE +#undef CHECK +} + +static bool exif_scan_HEIF_header(image_info_type *ImageInfo, unsigned char *buf) +{ + isobmff_box_type box; + isobmff_item_pos_type pos; + unsigned char *data; + uint64_t limit; + int box_header_size, remain; + bool ret = false; + + for (size_t offset = php_ifd_get32u(buf, 1); ImageInfo->FileSize - 16 > offset; offset += box.size) { + if ((php_stream_seek(ImageInfo->infile, offset, SEEK_SET) < 0) || + (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)buf, 16) != 16)) { + break; + } + box_header_size = exif_isobmff_parse_box(buf, &box); + if (box.size < box_header_size) { + break; + } + if (box.type == FOURCC("meta")) { + limit = box.size - box_header_size; + if (limit < 36) { + break; + } + data = (unsigned char *)emalloc(limit); + remain = 16 - box_header_size; + if (remain) { + memcpy(data, buf + box_header_size, remain); + } + memset(&pos, 0, sizeof(pos)); + if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(data + remain), limit - remain) == limit - remain) { + exif_isobmff_parse_meta(data, data + limit, &pos); + } + if ((pos.size) && + (pos.size < ImageInfo->FileSize) && + (ImageInfo->FileSize - pos.size >= pos.offset) && + (php_stream_seek(ImageInfo->infile, pos.offset + 2, SEEK_SET) >= 0)) { + if (limit >= pos.size - 2) { + limit = pos.size - 2; + } else { + limit = pos.size - 2; + efree(data); + data = (unsigned char *)emalloc(limit); + } + if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)data, limit) == limit) { + exif_process_APP1(ImageInfo, (char*)data, limit, pos.offset + 2); + ret = true; + } + } + efree(data); + break; + } + if (offset + box.size < offset) { + break; + } + } + + return ret; +} + /* {{{ exif_scan_FILE_header * Parse the marker stream until SOS or EOI is seen; */ static bool exif_scan_FILE_header(image_info_type *ImageInfo) { - unsigned char file_header[8]; + unsigned char file_header[16]; ImageInfo->FileType = IMAGE_FILETYPE_UNKNOWN; @@ -4344,6 +4512,17 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo) exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid TIFF file"); return false; } + } else if ((ImageInfo->FileSize > 16) && + (!memcmp(file_header + 4, "ftyp", 4)) && + (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(file_header + 8), 4) == 4) && + ((!memcmp(file_header + 8, "heic", 4)) || (!memcmp(file_header + 8, "heix", 4)) || (!memcmp(file_header + 8, "mif1", 4)))) { + if (exif_scan_HEIF_header(ImageInfo, file_header)) { + ImageInfo->FileType = IMAGE_FILETYPE_HEIF; + return true; + } else { + exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid HEIF file"); + return false; + } } else { exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "File not supported"); return false; diff --git a/ext/exif/tests/exif029.phpt b/ext/exif/tests/exif029.phpt new file mode 100644 index 0000000000000..f2eadbfe5d2aa --- /dev/null +++ b/ext/exif/tests/exif029.phpt @@ -0,0 +1,145 @@ +--TEST-- +Check for exif_read_data, HEIF with IFD0 and EXIF data in Motorola byte-order. +--EXTENSIONS-- +exif +--INI-- +output_handler= +zlib.output_compression=0 +--FILE-- + +--EXPECTF-- +array(53) { + ["FileName"]=> + string(13) "image029.heic" + ["FileDateTime"]=> + int(%d) + ["FileSize"]=> + int(42199) + ["FileType"]=> + int(20) + ["MimeType"]=> + string(10) "image/heif" + ["SectionsFound"]=> + string(19) "ANY_TAG, IFD0, EXIF" + ["COMPUTED"]=> + array(3) { + ["IsColor"]=> + int(0) + ["ByteOrderMotorola"]=> + int(1) + ["ApertureFNumber"]=> + string(5) "f/1.8" + } + ["Make"]=> + string(5) "Apple" + ["Model"]=> + string(26) "iPhone SE (3rd generation)" + ["Orientation"]=> + int(1) + ["XResolution"]=> + string(4) "72/1" + ["YResolution"]=> + string(4) "72/1" + ["ResolutionUnit"]=> + int(2) + ["Software"]=> + string(6) "17.2.1" + ["DateTime"]=> + string(19) "2024:02:21 16:03:50" + ["HostComputer"]=> + string(26) "iPhone SE (3rd generation)" + ["TileWidth"]=> + int(512) + ["TileLength"]=> + int(512) + ["Exif_IFD_Pointer"]=> + int(264) + ["ExposureTime"]=> + string(4) "1/60" + ["FNumber"]=> + string(3) "9/5" + ["ExposureProgram"]=> + int(2) + ["ISOSpeedRatings"]=> + int(200) + ["ExifVersion"]=> + string(4) "0232" + ["DateTimeOriginal"]=> + string(19) "2024:02:21 16:03:50" + ["DateTimeDigitized"]=> + string(19) "2024:02:21 16:03:50" + ["OffsetTime"]=> + string(6) "+08:00" + ["OffsetTimeOriginal"]=> + string(6) "+08:00" + ["OffsetTimeDigitized"]=> + string(6) "+08:00" + ["ShutterSpeedValue"]=> + string(12) "159921/27040" + ["ApertureValue"]=> + string(11) "54823/32325" + ["BrightnessValue"]=> + string(11) "29968/13467" + ["ExposureBiasValue"]=> + string(3) "0/1" + ["MeteringMode"]=> + int(5) + ["Flash"]=> + int(16) + ["FocalLength"]=> + string(7) "399/100" + ["SubjectLocation"]=> + array(4) { + [0]=> + int(1995) + [1]=> + int(1507) + [2]=> + int(2217) + [3]=> + int(1332) + } + ["MakerNote"]=> + string(9) "Apple iOS" + ["SubSecTimeOriginal"]=> + string(3) "598" + ["SubSecTimeDigitized"]=> + string(3) "598" + ["ColorSpace"]=> + int(65535) + ["ExifImageWidth"]=> + int(4032) + ["ExifImageLength"]=> + int(3024) + ["SensingMethod"]=> + int(2) + ["SceneType"]=> + string(1) "" + ["ExposureMode"]=> + int(0) + ["WhiteBalance"]=> + int(0) + ["DigitalZoomRatio"]=> + string(7) "756/151" + ["FocalLengthIn35mmFilm"]=> + int(140) + ["UndefinedTag:0xA432"]=> + array(4) { + [0]=> + string(15) "4183519/1048501" + [1]=> + string(15) "4183519/1048501" + [2]=> + string(3) "9/5" + [3]=> + string(3) "9/5" + } + ["UndefinedTag:0xA433"]=> + string(5) "Apple" + ["UndefinedTag:0xA434"]=> + string(51) "iPhone SE (3rd generation) back camera 3.99mm f/1.8" + ["UndefinedTag:0xA460"]=> + int(2) +} diff --git a/ext/exif/tests/heic_box_overflow.phpt b/ext/exif/tests/heic_box_overflow.phpt new file mode 100644 index 0000000000000..b3a5e42df91fc --- /dev/null +++ b/ext/exif/tests/heic_box_overflow.phpt @@ -0,0 +1,27 @@ +--TEST-- +HEIC box overflow +--EXTENSIONS-- +exif +--FILE-- + +--CLEAN-- + +--EXPECTF-- +Warning: exif_read_data(heic_box_overflow): Invalid HEIF file in %s on line %d +bool(false) diff --git a/ext/exif/tests/image029.heic b/ext/exif/tests/image029.heic new file mode 100644 index 0000000000000..99f8186d0723b Binary files /dev/null and b/ext/exif/tests/image029.heic differ diff --git a/ext/exif/tests/oss_fuzz_442954659/input b/ext/exif/tests/oss_fuzz_442954659/input new file mode 100644 index 0000000000000..5049d7e79d107 Binary files /dev/null and b/ext/exif/tests/oss_fuzz_442954659/input differ diff --git a/ext/exif/tests/oss_fuzz_442954659/oss_fuzz_442954659.phpt b/ext/exif/tests/oss_fuzz_442954659/oss_fuzz_442954659.phpt new file mode 100644 index 0000000000000..131b2c5be9808 --- /dev/null +++ b/ext/exif/tests/oss_fuzz_442954659/oss_fuzz_442954659.phpt @@ -0,0 +1,10 @@ +--TEST-- +OSS-Fuzz #442954659 (zero-size box in HEIF file causes infinite loop) +--EXTENSIONS-- +exif +--FILE-- + +--EXPECTF-- +Warning: exif_read_data(%s): Invalid HEIF file in %s on line %d diff --git a/ext/exif/tests/oss_fuzz_444479893/input b/ext/exif/tests/oss_fuzz_444479893/input new file mode 100644 index 0000000000000..91e083c9c6271 Binary files /dev/null and b/ext/exif/tests/oss_fuzz_444479893/input differ diff --git a/ext/exif/tests/oss_fuzz_444479893/oss_fuzz_444479893.phpt b/ext/exif/tests/oss_fuzz_444479893/oss_fuzz_444479893.phpt new file mode 100644 index 0000000000000..b03635400f0a6 --- /dev/null +++ b/ext/exif/tests/oss_fuzz_444479893/oss_fuzz_444479893.phpt @@ -0,0 +1,10 @@ +--TEST-- +OSS-Fuzz #442954659 (Crash in exif_scan_HEIF_header) +--EXTENSIONS-- +exif +--FILE-- + +--EXPECTF-- +Warning: exif_read_data(%s): Invalid HEIF file in %s on line %d diff --git a/ext/ffi/tests/025.phpt b/ext/ffi/tests/025.phpt index b1cdab9463e68..817d12806deac 100644 --- a/ext/ffi/tests/025.phpt +++ b/ext/ffi/tests/025.phpt @@ -39,6 +39,8 @@ object(FFI\CData:char)#%d (1) { ["cdata"]=> string(1) "a" } + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d object(FFI\CData:char)#%d (1) { ["cdata"]=> string(1) "b" diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 143b8ba080fc5..baae757154950 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -31,10 +31,11 @@ #include "php_ini.h" #include "ext/standard/info.h" #include "ext/standard/file.h" /* needed for context stuff */ +#include "Zend/zend_attributes.h" +#include "Zend/zend_exceptions.h" #include "php_fileinfo.h" #include "fileinfo_arginfo.h" #include "fopen_wrappers.h" /* needed for is_url */ -#include "Zend/zend_exceptions.h" static zend_object_handlers finfo_object_handlers; zend_class_entry *finfo_class_entry; @@ -153,22 +154,10 @@ PHP_FUNCTION(finfo_open) } else if (file && *file) { /* user specified file, perform open_basedir checks */ if (php_check_open_basedir(file)) { - if (object) { - zend_restore_error_handling(&zeh); - if (!EG(exception)) { - zend_throw_exception(NULL, "Constructor failed", 0); - } - } - RETURN_FALSE; + goto err; } if (!expand_filepath_with_mode(file, resolved_path, NULL, 0, CWD_EXPAND)) { - if (object) { - zend_restore_error_handling(&zeh); - if (!EG(exception)) { - zend_throw_exception(NULL, "Constructor failed", 0); - } - } - RETURN_FALSE; + goto err; } file = resolved_path; } @@ -177,37 +166,35 @@ PHP_FUNCTION(finfo_open) if (magic == NULL) { php_error_docref(NULL, E_WARNING, "Invalid mode '" ZEND_LONG_FMT "'.", options); - if (object) { - zend_restore_error_handling(&zeh); - if (!EG(exception)) { - zend_throw_exception(NULL, "Constructor failed", 0); - } - } - RETURN_FALSE; + goto err; } if (magic_load(magic, file) == -1) { php_error_docref(NULL, E_WARNING, "Failed to load magic database at \"%s\"", file); magic_close(magic); - if (object) { - zend_restore_error_handling(&zeh); - if (!EG(exception)) { - zend_throw_exception(NULL, "Constructor failed", 0); - } - } - RETURN_FALSE; + goto err; } if (object) { zend_restore_error_handling(&zeh); finfo_object *obj = Z_FINFO_P(object); obj->magic = magic; + return; } else { zend_object *zobj = finfo_objects_new(finfo_class_entry); finfo_object *obj = php_finfo_fetch_object(zobj); obj->magic = magic; RETURN_OBJ(zobj); } + +err: + if (object) { + zend_restore_error_handling(&zeh); + if (!EG(exception)) { + zend_throw_exception(NULL, "Constructor failed", 0); + } + } + RETURN_FALSE; } /* }}} */ @@ -356,6 +343,13 @@ PHP_FUNCTION(finfo_buffer) RETURN_THROWS(); } + if (ZEND_NUM_ARGS() == 4 || (hasThis() && ZEND_NUM_ARGS() == 3)) { + php_error_docref(NULL, E_DEPRECATED, "The $context parameter has no effect for finfo_buffer()"); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } + } + if (!Z_FINFO_P(self)->magic) { zend_throw_error(NULL, "Invalid finfo object"); RETURN_THROWS(); diff --git a/ext/fileinfo/fileinfo.stub.php b/ext/fileinfo/fileinfo.stub.php index 2dba0fe2659ef..238ad7c14809b 100644 --- a/ext/fileinfo/fileinfo.stub.php +++ b/ext/fileinfo/fileinfo.stub.php @@ -92,6 +92,7 @@ public function set_flags(int $flags): true {} /** @refcount 1 */ function finfo_open(int $flags = FILEINFO_NONE, ?string $magic_database = null): finfo|false {} +#[\Deprecated(since: '8.5', message: 'as finfo objects are freed automatically')] function finfo_close(finfo $finfo): true {} function finfo_set_flags(finfo $finfo, int $flags): true {} diff --git a/ext/fileinfo/fileinfo_arginfo.h b/ext/fileinfo/fileinfo_arginfo.h index 024e7d4b6bd59..ac6ba0f591f98 100644 --- a/ext/fileinfo/fileinfo_arginfo.h +++ b/ext/fileinfo/fileinfo_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d5bc322159e4af87077c07ddaca0a77803b4743a */ + * Stub hash: 311d1049e32af017b44e260a00f13830714b1e96 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_finfo_open, 0, 0, finfo, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "FILEINFO_NONE") @@ -63,7 +63,7 @@ ZEND_FUNCTION(mime_content_type); static const zend_function_entry ext_functions[] = { ZEND_FE(finfo_open, arginfo_finfo_open) - ZEND_FE(finfo_close, arginfo_finfo_close) + ZEND_RAW_FENTRY("finfo_close", zif_finfo_close, arginfo_finfo_close, ZEND_ACC_DEPRECATED, NULL, NULL) ZEND_FE(finfo_set_flags, arginfo_finfo_set_flags) ZEND_FE(finfo_file, arginfo_finfo_file) ZEND_FE(finfo_buffer, arginfo_finfo_buffer) @@ -96,6 +96,14 @@ static void register_fileinfo_symbols(int module_number) #endif REGISTER_LONG_CONSTANT("FILEINFO_APPLE", MAGIC_APPLE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILEINFO_EXTENSION", MAGIC_EXTENSION, CONST_PERSISTENT); + + + zend_attribute *attribute_Deprecated_func_finfo_close_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "finfo_close", sizeof("finfo_close") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_finfo_close_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_finfo_close_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_finfo_close_0_arg1_str = zend_string_init("as finfo objects are freed automatically", strlen("as finfo objects are freed automatically"), 1); + ZVAL_STR(&attribute_Deprecated_func_finfo_close_0->args[1].value, attribute_Deprecated_func_finfo_close_0_arg1_str); + attribute_Deprecated_func_finfo_close_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_finfo(void) diff --git a/ext/fileinfo/tests/finfo_buffer_deprecated_context_param.phpt b/ext/fileinfo/tests/finfo_buffer_deprecated_context_param.phpt new file mode 100644 index 0000000000000..ef4c736999d80 --- /dev/null +++ b/ext/fileinfo/tests/finfo_buffer_deprecated_context_param.phpt @@ -0,0 +1,20 @@ +--TEST-- +finfo_buffer() deprecated $context param +--EXTENSIONS-- +fileinfo +--FILE-- +buffer($buffer, FILEINFO_NONE, null)); + +?> +--EXPECTF-- +Deprecated: finfo_buffer(): The $context parameter has no effect for finfo_buffer() in %s on line %d +string(36) "ASCII text, with no line terminators" + +Deprecated: finfo::buffer(): The $context parameter has no effect for finfo_buffer() in %s on line %d +string(36) "ASCII text, with no line terminators" diff --git a/ext/fileinfo/tests/finfo_close_basic.phpt b/ext/fileinfo/tests/finfo_close_basic.phpt index cdaf4b23b0002..1abd7216390dc 100644 --- a/ext/fileinfo/tests/finfo_close_basic.phpt +++ b/ext/fileinfo/tests/finfo_close_basic.phpt @@ -23,6 +23,8 @@ unset( $finfo ); *** Testing finfo_close() : basic functionality *** object(finfo)#%d (0) { } + +Deprecated: Function finfo_close() is deprecated since 8.5, as finfo objects are freed automatically in %s on line %d bool(true) object(finfo)#%d (%d) { } diff --git a/ext/fileinfo/tests/finfo_close_error.phpt b/ext/fileinfo/tests/finfo_close_error.phpt index c43597f26a4e5..c7873b462724e 100644 --- a/ext/fileinfo/tests/finfo_close_error.phpt +++ b/ext/fileinfo/tests/finfo_close_error.phpt @@ -15,8 +15,10 @@ try { } ?> ---EXPECT-- +--EXPECTF-- *** Testing finfo_close() : error conditions *** -- Testing finfo_close() function with wrong resource type -- + +Deprecated: Function finfo_close() is deprecated since 8.5, as finfo objects are freed automatically in %s on line %d finfo_close(): Argument #1 ($finfo) must be of type finfo, resource given diff --git a/ext/filter/callback_filter.c b/ext/filter/callback_filter.c index b6d57739b2b9b..719b66767980f 100644 --- a/ext/filter/callback_filter.c +++ b/ext/filter/callback_filter.c @@ -16,7 +16,7 @@ #include "php_filter.h" -void php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL) { zval retval; int status; @@ -25,7 +25,7 @@ void php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL) zend_type_error("%s(): Option must be a valid callback", get_active_function_name()); zval_ptr_dtor(value); ZVAL_NULL(value); - return; + return SUCCESS; } status = call_user_function(NULL, NULL, option_array, &retval, 1, value); @@ -37,4 +37,5 @@ void php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL) zval_ptr_dtor(value); ZVAL_NULL(value); } + return SUCCESS; } diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 50eefb440d67a..4a928379877bc 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -27,13 +27,15 @@ ZEND_DECLARE_MODULE_GLOBALS(filter) +#include "zend_attributes.h" #include "filter_private.h" #include "filter_arginfo.h" +#include "zend_exceptions.h" typedef struct filter_list_entry { const char *name; int id; - void (*function)(PHP_INPUT_FILTER_PARAM_DECL); + zend_result (*function)(PHP_INPUT_FILTER_PARAM_DECL); } filter_list_entry; /* {{{ filter_list */ @@ -76,6 +78,9 @@ static const filter_list_entry filter_list[] = { static unsigned int php_sapi_filter(int arg, const char *var, char **val, size_t val_len, size_t *new_val_len); static unsigned int php_sapi_filter_init(void); +zend_class_entry *php_filter_exception_ce; +zend_class_entry *php_filter_failed_exception_ce; + /* {{{ filter_module_entry */ zend_module_entry filter_module_entry = { STANDARD_MODULE_HEADER, @@ -159,6 +164,9 @@ PHP_MINIT_FUNCTION(filter) sapi_register_input_filter(php_sapi_filter, php_sapi_filter_init); + php_filter_exception_ce = register_class_Filter_FilterException(zend_ce_exception); + php_filter_failed_exception_ce = register_class_Filter_FilterFailedException(php_filter_exception_ce); + return SUCCESS; } /* }}} */ @@ -250,6 +258,16 @@ static void php_zval_filter(zval *value, zend_long filter, zend_long flags, zval ce = Z_OBJCE_P(value); if (!ce->__tostring) { zval_ptr_dtor(value); + if (flags & FILTER_THROW_ON_FAILURE) { + zend_throw_exception_ex( + php_filter_failed_exception_ce, + 0, + "filter validation failed: object of type %s has no __toString() method", + ZSTR_VAL(ce->name) + ); + ZVAL_NULL(value); + return; + } /* #67167: doesn't return null on failure for objects */ if (flags & FILTER_NULL_ON_FAILURE) { ZVAL_NULL(value); @@ -263,7 +281,29 @@ static void php_zval_filter(zval *value, zend_long filter, zend_long flags, zval /* Here be strings */ convert_to_string(value); - filter_func.function(value, flags, options, charset); + zend_string *copy_for_throwing = NULL; + if (flags & FILTER_THROW_ON_FAILURE) { + copy_for_throwing = zend_string_copy(Z_STR_P(value)); + } + + zend_result result = filter_func.function(value, flags, options, charset); + + if (flags & FILTER_THROW_ON_FAILURE) { + ZEND_ASSERT(copy_for_throwing != NULL); + if (result == FAILURE) { + zend_throw_exception_ex( + php_filter_failed_exception_ce, + 0, + "filter validation failed: filter %s not satisfied by '%s'", + filter_func.name, + ZSTR_VAL(copy_for_throwing) + ); + zend_string_delref(copy_for_throwing); + return; + } + zend_string_delref(copy_for_throwing); + copy_for_throwing = NULL; + } handle_default: if (options && Z_TYPE_P(options) == IS_ARRAY && @@ -449,7 +489,8 @@ PHP_FUNCTION(filter_has_var) static void php_filter_call( zval *filtered, zend_long filter, HashTable *filter_args_ht, zend_long filter_args_long, - zend_long filter_flags + zend_long filter_flags, + uint32_t options_arg_num ) /* {{{ */ { zval *options = NULL; char *charset = NULL; @@ -491,10 +532,28 @@ static void php_filter_call( } } + /* Cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE */ + if ((filter_flags & FILTER_NULL_ON_FAILURE) && (filter_flags & FILTER_THROW_ON_FAILURE)) { + zval_ptr_dtor(filtered); + ZVAL_NULL(filtered); + zend_argument_value_error( + options_arg_num, + "cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE" + ); + return; + } + if (Z_TYPE_P(filtered) == IS_ARRAY) { if (filter_flags & FILTER_REQUIRE_SCALAR) { zval_ptr_dtor(filtered); - if (filter_flags & FILTER_NULL_ON_FAILURE) { + if (filter_flags & FILTER_THROW_ON_FAILURE) { + ZVAL_NULL(filtered); + zend_throw_exception( + php_filter_failed_exception_ce, + "filter validation failed: not a scalar value (got an array)", + 0 + ); + } else if (filter_flags & FILTER_NULL_ON_FAILURE) { ZVAL_NULL(filtered); } else { ZVAL_FALSE(filtered); @@ -505,6 +564,17 @@ static void php_filter_call( return; } if (filter_flags & FILTER_REQUIRE_ARRAY) { + if (filter_flags & FILTER_THROW_ON_FAILURE) { + zend_throw_exception_ex( + php_filter_failed_exception_ce, + 0, + "filter validation failed: not an array (got %s)", + zend_zval_value_name(filtered) + ); + zval_ptr_dtor(filtered); + ZVAL_NULL(filtered); + return; + } zval_ptr_dtor(filtered); if (filter_flags & FILTER_NULL_ON_FAILURE) { ZVAL_NULL(filtered); @@ -515,6 +585,10 @@ static void php_filter_call( } php_zval_filter(filtered, filter, filter_flags, options, charset); + /* Don't wrap in an array if we are throwing an exception */ + if (EG(exception)) { + return; + } if (filter_flags & FILTER_FORCE_ARRAY) { zval tmp; ZVAL_COPY_VALUE(&tmp, filtered); @@ -529,7 +603,7 @@ static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op ) /* {{{ */ { if (!op_ht) { ZVAL_DUP(return_value, input); - php_filter_call(return_value, -1, NULL, op_long, FILTER_REQUIRE_ARRAY); + php_filter_call(return_value, -1, NULL, op_long, FILTER_REQUIRE_ARRAY, 2); } else { array_init(return_value); zend_string *arg_key; @@ -553,11 +627,23 @@ static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op zval nval; ZVAL_DEREF(tmp); ZVAL_DUP(&nval, tmp); + + if (Z_TYPE_P(arg_elm) != IS_ARRAY) { + zend_long filter_id = zval_get_long(arg_elm); + if (!PHP_FILTER_ID_EXISTS(filter_id)) { + php_error_docref(NULL, E_WARNING, "Unknown filter with ID " ZEND_LONG_FMT, filter_id); + } + } + php_filter_call(&nval, -1, Z_TYPE_P(arg_elm) == IS_ARRAY ? Z_ARRVAL_P(arg_elm) : NULL, Z_TYPE_P(arg_elm) == IS_ARRAY ? 0 : zval_get_long(arg_elm), - FILTER_REQUIRE_SCALAR + FILTER_REQUIRE_SCALAR, + 2 ); + if (EG(exception)) { + RETURN_THROWS(); + } zend_hash_update(Z_ARRVAL_P(return_value), arg_key, &nval); } } ZEND_HASH_FOREACH_END(); @@ -597,11 +683,35 @@ PHP_FUNCTION(filter_input) if (!filter_args_ht) { filter_flags = filter_args_long; } else { - zval *option, *opt, *def; + zval *option; if ((option = zend_hash_str_find(filter_args_ht, "flags", sizeof("flags") - 1)) != NULL) { filter_flags = zval_get_long(option); } + } + + /* Cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE */ + if ((filter_flags & FILTER_NULL_ON_FAILURE) && (filter_flags & FILTER_THROW_ON_FAILURE)) { + zend_argument_value_error( + 4, + "cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE" + ); + RETURN_THROWS(); + } + + if (filter_flags & FILTER_THROW_ON_FAILURE) { + zend_throw_exception_ex( + php_filter_failed_exception_ce, + 0, + "input value '%s' not found", + ZSTR_VAL(var) + ); + RETURN_THROWS(); + } + /* FILTER_THROW_ON_FAILURE overrides defaults, needs to be checked + * before the default is used. */ + if (filter_args_ht) { + zval *opt, *def; if ((opt = zend_hash_str_find_deref(filter_args_ht, "options", sizeof("options") - 1)) != NULL && Z_TYPE_P(opt) == IS_ARRAY && (def = zend_hash_str_find_deref(Z_ARRVAL_P(opt), "default", sizeof("default") - 1)) != NULL @@ -625,7 +735,7 @@ PHP_FUNCTION(filter_input) ZVAL_DUP(return_value, tmp); - php_filter_call(return_value, filter, filter_args_ht, filter_args_long, FILTER_REQUIRE_SCALAR); + php_filter_call(return_value, filter, filter_args_ht, filter_args_long, FILTER_REQUIRE_SCALAR, 4); } /* }}} */ @@ -651,7 +761,7 @@ PHP_FUNCTION(filter_var) ZVAL_DUP(return_value, data); - php_filter_call(return_value, filter, filter_args_ht, filter_args_long, FILTER_REQUIRE_SCALAR); + php_filter_call(return_value, filter, filter_args_ht, filter_args_long, FILTER_REQUIRE_SCALAR, 3); } /* }}} */ diff --git a/ext/filter/filter.stub.php b/ext/filter/filter.stub.php index 030de50f51890..4332f9261e982 100644 --- a/ext/filter/filter.stub.php +++ b/ext/filter/filter.stub.php @@ -2,6 +2,7 @@ /** @generate-class-entries */ +namespace { /** * @var int * @cvalue PARSE_POST @@ -54,6 +55,11 @@ * @cvalue FILTER_NULL_ON_FAILURE */ const FILTER_NULL_ON_FAILURE = UNKNOWN; +/** + * @var int + * @cvalue FILTER_THROW_ON_FAILURE + */ +const FILTER_THROW_ON_FAILURE = UNKNOWN; /** * @var int @@ -121,14 +127,14 @@ /** * @var int * @cvalue FILTER_SANITIZE_STRING - * @deprecated */ +#[\Deprecated(since: '8.1', message: 'use htmlspecialchars() instead')] const FILTER_SANITIZE_STRING = UNKNOWN; /** * @var int * @cvalue FILTER_SANITIZE_STRING - * @deprecated */ +#[\Deprecated(since: '8.1', message: 'use htmlspecialchars() instead')] const FILTER_SANITIZE_STRIPPED = UNKNOWN; /** * @var int @@ -313,3 +319,13 @@ function filter_var_array(array $array, array|int $options = FILTER_DEFAULT, boo function filter_list(): array {} function filter_id(string $name): int|false {} + +} + +namespace Filter { + + class FilterException extends \Exception {} + + class FilterFailedException extends FilterException {} + +} diff --git a/ext/filter/filter_arginfo.h b/ext/filter/filter_arginfo.h index a05806c5e1201..c777b6ffe77e0 100644 --- a/ext/filter/filter_arginfo.h +++ b/ext/filter/filter_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c3f3240137eaa89316276920acf35f975b2dd8f9 */ + * Stub hash: c3eb55dfec619af1e46be206f51a2b0893ed399f */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_filter_has_var, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, input_type, IS_LONG, 0) @@ -69,6 +69,7 @@ static void register_filter_symbols(int module_number) REGISTER_LONG_CONSTANT("FILTER_REQUIRE_ARRAY", FILTER_REQUIRE_ARRAY, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_FORCE_ARRAY", FILTER_FORCE_ARRAY, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_NULL_ON_FAILURE", FILTER_NULL_ON_FAILURE, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("FILTER_THROW_ON_FAILURE", FILTER_THROW_ON_FAILURE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_VALIDATE_INT", FILTER_VALIDATE_INT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_VALIDATE_BOOLEAN", FILTER_VALIDATE_BOOL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_VALIDATE_BOOL", FILTER_VALIDATE_BOOL, CONST_PERSISTENT); @@ -81,8 +82,8 @@ static void register_filter_symbols(int module_number) REGISTER_LONG_CONSTANT("FILTER_VALIDATE_MAC", FILTER_VALIDATE_MAC, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_DEFAULT", FILTER_DEFAULT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_UNSAFE_RAW", FILTER_UNSAFE_RAW, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILTER_SANITIZE_STRING", FILTER_SANITIZE_STRING, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("FILTER_SANITIZE_STRIPPED", FILTER_SANITIZE_STRING, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_FILTER_SANITIZE_STRING = REGISTER_LONG_CONSTANT("FILTER_SANITIZE_STRING", FILTER_SANITIZE_STRING, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_FILTER_SANITIZE_STRIPPED = REGISTER_LONG_CONSTANT("FILTER_SANITIZE_STRIPPED", FILTER_SANITIZE_STRING, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_ENCODED", FILTER_SANITIZE_ENCODED, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_SPECIAL_CHARS", FILTER_SANITIZE_SPECIAL_CHARS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_FULL_SPECIAL_CHARS", FILTER_SANITIZE_FULL_SPECIAL_CHARS, CONST_PERSISTENT); @@ -114,4 +115,38 @@ static void register_filter_symbols(int module_number) REGISTER_LONG_CONSTANT("FILTER_FLAG_GLOBAL_RANGE", FILTER_FLAG_GLOBAL_RANGE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_FLAG_HOSTNAME", FILTER_FLAG_HOSTNAME, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_FLAG_EMAIL_UNICODE", FILTER_FLAG_EMAIL_UNICODE, CONST_PERSISTENT); + + + zend_attribute *attribute_Deprecated_const_FILTER_SANITIZE_STRING_0 = zend_add_global_constant_attribute(const_FILTER_SANITIZE_STRING, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_FILTER_SANITIZE_STRING_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_FILTER_SANITIZE_STRING_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_FILTER_SANITIZE_STRING_0_arg1_str = zend_string_init("use htmlspecialchars() instead", strlen("use htmlspecialchars() instead"), 1); + ZVAL_STR(&attribute_Deprecated_const_FILTER_SANITIZE_STRING_0->args[1].value, attribute_Deprecated_const_FILTER_SANITIZE_STRING_0_arg1_str); + attribute_Deprecated_const_FILTER_SANITIZE_STRING_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0 = zend_add_global_constant_attribute(const_FILTER_SANITIZE_STRIPPED, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0->args[1].value, attribute_Deprecated_const_FILTER_SANITIZE_STRING_0_arg1_str); + attribute_Deprecated_const_FILTER_SANITIZE_STRIPPED_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); +} + +static zend_class_entry *register_class_Filter_FilterException(zend_class_entry *class_entry_Exception) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "Filter", "FilterException", NULL); + class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Exception, 0); + + return class_entry; +} + +static zend_class_entry *register_class_Filter_FilterFailedException(zend_class_entry *class_entry_Filter_FilterException) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "Filter", "FilterFailedException", NULL); + class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Filter_FilterException, 0); + + return class_entry; } diff --git a/ext/filter/filter_private.h b/ext/filter/filter_private.h index a1bbb500f8db4..709b7fbc45edc 100644 --- a/ext/filter/filter_private.h +++ b/ext/filter/filter_private.h @@ -24,6 +24,7 @@ #define FILTER_FORCE_ARRAY 0x4000000 #define FILTER_NULL_ON_FAILURE 0x8000000 +#define FILTER_THROW_ON_FAILURE 0x10000000 #define FILTER_FLAG_ALLOW_OCTAL 0x0001 #define FILTER_FLAG_ALLOW_HEX 0x0002 @@ -50,7 +51,7 @@ #define FILTER_FLAG_IPV6 0x00200000 #define FILTER_FLAG_NO_RES_RANGE 0x00400000 #define FILTER_FLAG_NO_PRIV_RANGE 0x00800000 -#define FILTER_FLAG_GLOBAL_RANGE 0x10000000 +#define FILTER_FLAG_GLOBAL_RANGE 0x20000000 #define FILTER_FLAG_HOSTNAME 0x100000 @@ -93,9 +94,18 @@ || (id >= FILTER_VALIDATE_ALL && id <= FILTER_VALIDATE_LAST) \ || id == FILTER_CALLBACK) + +/* When using FILTER_THROW_ON_FAILURE, we can't actually throw the error here + * because we don't have access to the name of the filter. Returning FAILURE + * from the filter handler indicates that validation failed *and* an exception + * should thus be thrown. */ #define RETURN_VALIDATION_FAILED \ if (EG(exception)) { \ - return; \ + return SUCCESS; \ + } else if (flags & FILTER_THROW_ON_FAILURE) { \ + zval_ptr_dtor(value); \ + ZVAL_NULL(value); \ + return FAILURE; \ } else if (flags & FILTER_NULL_ON_FAILURE) { \ zval_ptr_dtor(value); \ ZVAL_NULL(value); \ @@ -103,7 +113,7 @@ zval_ptr_dtor(value); \ ZVAL_FALSE(value); \ } \ - return; \ + return SUCCESS; \ #define PHP_FILTER_TRIM_DEFAULT(p, len) PHP_FILTER_TRIM_DEFAULT_EX(p, len, 1); diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 0dd307122345c..2dec236114182 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -16,10 +16,11 @@ +----------------------------------------------------------------------+ */ +#include "zend_exceptions.h" #include "php_filter.h" #include "filter_private.h" -#include "ext/standard/url.h" #include "ext/pcre/php_pcre.h" +#include "ext/uri/php_uri.h" #include "zend_multiply.h" @@ -89,6 +90,8 @@ #define FORMAT_IPV4 4 #define FORMAT_IPV6 6 +#define URL_OPTION_URI_PARSER_CLASS "uri_parser_class" + static bool _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]); static bool php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */ @@ -195,7 +198,7 @@ static bool php_filter_parse_hex(const char *str, size_t str_len, zend_long *ret } /* }}} */ -void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { zval *option_val; zend_long min_range, max_range, option_flags; @@ -266,12 +269,12 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } else { zval_ptr_dtor(value); ZVAL_LONG(value, ctx_value); - return; } + return SUCCESS; } /* }}} */ -void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { const char *str = Z_STRVAL_P(value); size_t len = Z_STRLEN_P(value); @@ -337,10 +340,11 @@ void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ zval_ptr_dtor(value); ZVAL_BOOL(value, ret); } + return SUCCESS; } /* }}} */ -void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { size_t len; const char *str, *end; @@ -467,10 +471,11 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ RETURN_VALIDATION_FAILED } efree(num); + return SUCCESS; } /* }}} */ -void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { zval *option_val; zend_string *regexp; @@ -503,6 +508,7 @@ void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ if (rc < 0) { RETURN_VALIDATION_FAILED } + return SUCCESS; } static bool php_filter_validate_domain_ex(const zend_string *domain, zend_long flags) /* {{{ */ @@ -557,11 +563,12 @@ static bool php_filter_validate_domain_ex(const zend_string *domain, zend_long f } /* }}} */ -void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { if (!php_filter_validate_domain_ex(Z_STR_P(value), flags)) { RETURN_VALIDATION_FAILED } + return SUCCESS; } /* }}} */ @@ -589,9 +596,8 @@ static bool php_filter_is_valid_ipv6_hostname(const zend_string *s) return *ZSTR_VAL(s) == '[' && *t == ']' && _php_filter_validate_ipv6(ZSTR_VAL(s) + 1, ZSTR_LEN(s) - 2, NULL); } -void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { - php_url *url; size_t old_len = Z_STRLEN_P(value); php_filter_url(value, flags, option_array, charset); @@ -600,56 +606,71 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ RETURN_VALIDATION_FAILED } - /* Use parse_url - if it returns false, we return NULL */ - url = php_url_parse_ex(Z_STRVAL_P(value), Z_STRLEN_P(value)); + /* Parse options */ + zval *option_val; + zend_string *parser_name; + int parser_name_set; + FETCH_STR_OPTION(parser_name, URL_OPTION_URI_PARSER_CLASS); + + const php_uri_parser *uri_parser = php_uri_get_parser(parser_name_set ? parser_name : NULL); + if (uri_parser == NULL) { + zend_value_error("%s(): \"uri_parser_class\" option has invalid value", get_active_function_name()); + RETURN_VALIDATION_FAILED + } - if (url == NULL) { + /* Parse the URI - if it fails, we return NULL */ + php_uri *uri = php_uri_parse_to_struct(uri_parser, Z_STRVAL_P(value), Z_STRLEN_P(value), PHP_URI_COMPONENT_READ_MODE_RAW, true); + if (uri == NULL) { RETURN_VALIDATION_FAILED } - if (url->scheme != NULL && - (zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) { + if (uri->scheme != NULL && + (zend_string_equals_literal_ci(uri->scheme, "http") || zend_string_equals_literal_ci(uri->scheme, "https"))) { - if (url->host == NULL) { - goto bad_url; + if (uri->host == NULL) { + php_uri_struct_free(uri); + RETURN_VALIDATION_FAILED } if ( + /* Skipping these checks is possible because the new URI implementations perform comprehensive validations. */ + strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0 && /* An IPv6 enclosed by square brackets is a valid hostname.*/ - !php_filter_is_valid_ipv6_hostname(url->host) && + !php_filter_is_valid_ipv6_hostname(uri->host) && /* Validate domain. * This includes a loose check for an IPv4 address. */ - !php_filter_validate_domain_ex(url->host, FILTER_FLAG_HOSTNAME) + !php_filter_validate_domain_ex(uri->host, FILTER_FLAG_HOSTNAME) ) { - php_url_free(url); + php_uri_struct_free(uri); RETURN_VALIDATION_FAILED } } - if ( - url->scheme == NULL || - /* some schemas allow the host to be empty */ - (url->host == NULL && (!zend_string_equals_literal(url->scheme, "mailto") && !zend_string_equals_literal(url->scheme, "news") && !zend_string_equals_literal(url->scheme, "file"))) || - ((flags & FILTER_FLAG_PATH_REQUIRED) && url->path == NULL) || ((flags & FILTER_FLAG_QUERY_REQUIRED) && url->query == NULL) + if (uri->scheme == NULL || + /* some schemes allow the host to be empty */ + (uri->host == NULL && (!zend_string_equals_literal(uri->scheme, "mailto") && !zend_string_equals_literal(uri->scheme, "news") && !zend_string_equals_literal(uri->scheme, "file"))) || + ((flags & FILTER_FLAG_PATH_REQUIRED) && uri->path == NULL) || ((flags & FILTER_FLAG_QUERY_REQUIRED) && uri->query == NULL) ) { -bad_url: - php_url_free(url); + php_uri_struct_free(uri); RETURN_VALIDATION_FAILED } - if ((url->user != NULL && !is_userinfo_valid(url->user)) - || (url->pass != NULL && !is_userinfo_valid(url->pass)) + if (strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0 && + ( + (uri->user != NULL && !is_userinfo_valid(uri->user)) || + (uri->password != NULL && !is_userinfo_valid(uri->password)) + ) ) { - php_url_free(url); + php_uri_struct_free(uri); RETURN_VALIDATION_FAILED - } - php_url_free(url); + php_uri_struct_free(uri); + return SUCCESS; } /* }}} */ -void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { /* * The regex below is based on a regex by Michael Rushton. @@ -715,6 +736,7 @@ void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ if (rc < 0) { RETURN_VALIDATION_FAILED } + return SUCCESS; } /* }}} */ @@ -975,7 +997,7 @@ static bool ipv6_get_status_flags(const int ip[8], bool *global, bool *reserved, * to throw out reserved ranges; multicast ranges... etc. If both allow_ipv4 * and allow_ipv6 flags flag are used, then the first dot or colon determine * the format */ -void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { int ip[8]; int mode; @@ -1003,7 +1025,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } if (!ipv4_get_status_flags(ip, &flag_global, &flag_reserved, &flag_private)) { - return; /* no special block */ + return SUCCESS; /* no special block */ } } else if (mode == FORMAT_IPV6) { @@ -1012,7 +1034,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } if (!ipv6_get_status_flags(ip, &flag_global, &flag_reserved, &flag_private)) { - return; /* no special block */ + return SUCCESS; /* no special block */ } } @@ -1027,10 +1049,11 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ if ((flags & FILTER_FLAG_NO_RES_RANGE) && flag_reserved == true) { RETURN_VALIDATION_FAILED } + return SUCCESS; } /* }}} */ -void php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ +zend_result php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { const char *input = Z_STRVAL_P(value); size_t input_len = Z_STRLEN_P(value); @@ -1089,5 +1112,6 @@ void php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ RETURN_VALIDATION_FAILED } } + return SUCCESS; } /* }}} */ diff --git a/ext/filter/php_filter.h b/ext/filter/php_filter.h index f782907898fca..48ad5cc07943e 100644 --- a/ext/filter/php_filter.h +++ b/ext/filter/php_filter.h @@ -53,27 +53,27 @@ ZEND_TSRMLS_CACHE_EXTERN() #define IF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(filter, v) #define PHP_INPUT_FILTER_PARAM_DECL zval *value, zend_long flags, zval *option_array, char *charset -void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_int(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_float(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_validate_mac(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_url(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_add_slashes(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_string(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_email(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_url(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_add_slashes(PHP_INPUT_FILTER_PARAM_DECL); -void php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL); +zend_result php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL); #endif /* FILTER_H */ diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c index ebc20e47711db..94cbd0c34bba7 100644 --- a/ext/filter/sanitizing_filters.c +++ b/ext/filter/sanitizing_filters.c @@ -168,7 +168,7 @@ static void filter_map_apply(zval *value, const filter_map *map) /* }}} */ /* {{{ php_filter_string */ -void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_string(PHP_INPUT_FILTER_PARAM_DECL) { size_t new_len; unsigned char enc[256] = {0}; @@ -206,23 +206,24 @@ void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL) } else { ZVAL_EMPTY_STRING(value); } - return; } + return SUCCESS; } /* }}} */ /* {{{ php_filter_encoded */ -void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL) { /* apply strip_high and strip_low filters */ php_filter_strip(value, flags); /* urlencode */ php_filter_encode_url(value, (unsigned char *)DEFAULT_URL_ENCODE, sizeof(DEFAULT_URL_ENCODE)-1); + return SUCCESS; } /* }}} */ /* {{{ php_filter_special_chars */ -void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL) { unsigned char enc[256] = {0}; @@ -239,11 +240,12 @@ void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL) } php_filter_encode_html(value, enc); + return SUCCESS; } /* }}} */ /* {{{ php_filter_full_special_chars */ -void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL) { zend_string *buf; int quotes; @@ -258,11 +260,12 @@ void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL) /* charset_hint */ NULL, /* double_encode */ 0, /* quiet */ 0); zval_ptr_dtor(value); ZVAL_STR(value, buf); + return SUCCESS; } /* }}} */ /* {{{ php_filter_unsafe_raw */ -void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL) { /* Only if no flags are set (optimization) */ if (flags != 0 && Z_STRLEN_P(value) > 0) { @@ -285,6 +288,7 @@ void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL) zval_ptr_dtor(value); ZVAL_NULL(value); } + return SUCCESS; } /* }}} */ @@ -295,7 +299,7 @@ void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL) #define PUNCTUATION "<>#%\"" #define RESERVED ";/?:@&=" -void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_email(PHP_INPUT_FILTER_PARAM_DECL) { /* Check section 6 of rfc 822 http://www.faqs.org/rfcs/rfc822.html */ const unsigned char allowed_list[] = LOWALPHA HIALPHA DIGIT "!#$%&'*+-=?^_`{|}~@.[]"; @@ -304,11 +308,12 @@ void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL) filter_map_init(&map); filter_map_update(&map, 1, allowed_list); filter_map_apply(value, &map); + return SUCCESS; } /* }}} */ /* {{{ php_filter_url */ -void php_filter_url(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_url(PHP_INPUT_FILTER_PARAM_DECL) { /* Strip all chars not part of section 5 of * http://www.faqs.org/rfcs/rfc1738.html */ @@ -318,11 +323,12 @@ void php_filter_url(PHP_INPUT_FILTER_PARAM_DECL) filter_map_init(&map); filter_map_update(&map, 1, allowed_list); filter_map_apply(value, &map); + return SUCCESS; } /* }}} */ /* {{{ php_filter_number_int */ -void php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL) { /* strip everything [^0-9+-] */ const unsigned char allowed_list[] = "+-" DIGIT; @@ -331,11 +337,12 @@ void php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL) filter_map_init(&map); filter_map_update(&map, 1, allowed_list); filter_map_apply(value, &map); + return SUCCESS; } /* }}} */ /* {{{ php_filter_number_float */ -void php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL) { /* strip everything [^0-9+-] */ const unsigned char allowed_list[] = "+-" DIGIT; @@ -355,15 +362,17 @@ void php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL) filter_map_update(&map, 4, (const unsigned char *) "eE"); } filter_map_apply(value, &map); + return SUCCESS; } /* }}} */ /* {{{ php_filter_add_slashes */ -void php_filter_add_slashes(PHP_INPUT_FILTER_PARAM_DECL) +zend_result php_filter_add_slashes(PHP_INPUT_FILTER_PARAM_DECL) { zend_string *buf = php_addslashes(Z_STR_P(value)); zval_ptr_dtor(value); ZVAL_STR(value, buf); + return SUCCESS; } /* }}} */ diff --git a/ext/filter/tests/025.phpt b/ext/filter/tests/025.phpt index d8e06e3ac20cc..05459fcb1cb27 100644 --- a/ext/filter/tests/025.phpt +++ b/ext/filter/tests/025.phpt @@ -16,24 +16,24 @@ var_dump(filter_var(".", FILTER_SANITIZE_STRING)); echo "Done\n"; ?> --EXPECTF-- -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(0) "" -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(0) "" -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(12) "!@#$%^&*()'"" -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(24) "!@#$%^&*()'"" -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(11) "`1234567890" -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(5) "`123`" -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(1) "." Done diff --git a/ext/filter/tests/026.phpt b/ext/filter/tests/026.phpt index db43df7949a0d..856f5325cb3b9 100644 --- a/ext/filter/tests/026.phpt +++ b/ext/filter/tests/026.phpt @@ -20,30 +20,30 @@ var_dump(filter_var("", FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_HIGH)); echo "Done\n"; ?> --EXPECTF-- -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(40) "Let me see you Stripped down to the bone" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(11) "!@#$%^&*()>" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(0) "" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(40) "Let me see you Stripped down to the bone" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(11) "!@#$%^&*()>" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(0) "" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(40) "Let me see you Stripped down to the bone" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(11) "!@#$%^&*()>" -Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(0) "" Done diff --git a/ext/filter/tests/039.phpt b/ext/filter/tests/039.phpt index 571d3a3265fc0..229feecd4475b 100644 --- a/ext/filter/tests/039.phpt +++ b/ext/filter/tests/039.phpt @@ -125,12 +125,18 @@ array(1) { ["var_name"]=> NULL } + +Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d array(1) { ["var_name"]=> string(0) "" } -- (5) + +Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d filter_var_array(): Argument #2 ($options) cannot contain empty keys + +Warning: filter_var_array(): Unknown filter with ID 0 in %s on line %d filter_var_array(): Argument #2 ($options) cannot contain empty keys Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d diff --git a/ext/filter/tests/042.phpt b/ext/filter/tests/042.phpt index 0795392f7acaa..28f346afeefc4 100644 --- a/ext/filter/tests/042.phpt +++ b/ext/filter/tests/042.phpt @@ -15,8 +15,8 @@ $a = filter_var($var, FILTER_SANITIZE_STRING, array("flags" => FILTER_FLAG_STRIP echo $a . "\n"; ?> --EXPECTF-- -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d XYZalert(/ext/filter+bypass/);ABC -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d XYZalert(/ext/filter+bypass/);ABC diff --git a/ext/filter/tests/062.phpt b/ext/filter/tests/062.phpt new file mode 100644 index 0000000000000..2623443314ad4 --- /dev/null +++ b/ext/filter/tests/062.phpt @@ -0,0 +1,184 @@ +--TEST-- +filter_var() and FILTER_VALIDATE_URL with different URI parsers +--EXTENSIONS-- +filter +--FILE-- + $parserName])); + } + + var_dump(filter_var("qwe", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://qwe", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("/tmp/test", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://www.example.com", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName])); + var_dump(filter_var("http://www.example.com", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_PATH_REQUIRED])); + var_dump(filter_var("http://www.example.com/path/at/the/server/", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_PATH_REQUIRED])); + var_dump(filter_var("http://www.example.com/index.html", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_QUERY_REQUIRED])); + var_dump(filter_var("http://www.example.com/index.php?a=b&c=d", FILTER_VALIDATE_URL, ["uri_parser_class" => $parserName, "flags" => FILTER_FLAG_QUERY_REQUIRED])); +} + +echo "RFC3986:\n"; +validateUrls(Uri\Rfc3986Uri::class); + +echo "\nWHATWG:\n"; +validateUrls(Uri\WhatWgUri::class); + +echo "Done\n"; +?> +--EXPECT-- +RFC3986: +string(29) "http://example.com/index.html" +string(32) "http://www.example.com/index.php" +string(31) "http://www.example/img/test.png" +string(27) "http://www.example/img/dir/" +string(26) "http://www.example/img/dir" +string(79) "http://www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com/" +bool(false) +bool(false) +string(261) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com." +bool(false) +string(48) "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]" +string(50) "http://[2001:db8:0:85a3:0:0:ac1f:8001]:123/me.html" +string(36) "http://[2001:db8:0:85a3::ac1f:8001]/" +string(12) "http://[::1]" +string(31) "http://cont-ains.h-yph-en-s.com" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(18) "file:///tmp/test.c" +string(26) "ftp://ftp.example.com/tmp/" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(18) "mailto:foo@bar.com" +string(17) "news:news.php.net" +string(14) "file://foo/bar" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(10) "http://qwe" +bool(false) +bool(false) +string(22) "http://www.example.com" +bool(false) +string(42) "http://www.example.com/path/at/the/server/" +bool(false) +string(40) "http://www.example.com/index.php?a=b&c=d" + +WHATWG: +string(29) "http://example.com/index.html" +string(32) "http://www.example.com/index.php" +string(31) "http://www.example/img/test.png" +string(27) "http://www.example/img/dir/" +string(26) "http://www.example/img/dir" +string(79) "http://www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com/" +bool(false) +bool(false) +string(261) "http://kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.kDTvHt1PPDgX5EiP2MwiXjcoWNOhhTuOVAUWJ3TmpBYCC9QoJV114LMYrV3Zl58.CQ1oT5Uq3jJt6Uhy3VH9u3Gi5YhfZCvZVKgLlaXNFhVKB1zJxvunR7SJa.com." +bool(false) +string(48) "http://[2001:0db8:0000:85a3:0000:0000:ac1f:8001]" +string(50) "http://[2001:db8:0:85a3:0:0:ac1f:8001]:123/me.html" +string(36) "http://[2001:db8:0:85a3::ac1f:8001]/" +string(12) "http://[::1]" +string(31) "http://cont-ains.h-yph-en-s.com" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(18) "file:///tmp/test.c" +string(26) "ftp://ftp.example.com/tmp/" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(18) "mailto:foo@bar.com" +string(17) "news:news.php.net" +string(14) "file://foo/bar" +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) +string(10) "http://qwe" +bool(false) +bool(false) +string(22) "http://www.example.com" +bool(false) +string(42) "http://www.example.com/path/at/the/server/" +bool(false) +string(40) "http://www.example.com/index.php?a=b&c=d" +Done diff --git a/ext/filter/tests/bug69203.phpt b/ext/filter/tests/bug69203.phpt index 3453c7c0adc6f..85356ba2a1349 100644 --- a/ext/filter/tests/bug69203.phpt +++ b/ext/filter/tests/bug69203.phpt @@ -10,7 +10,7 @@ var_dump(filter_var("\x7f", FILTER_SANITIZE_ENCODED, FILTER_FLAG_STRIP_HIGH)); var_dump(filter_var("\x7f", FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_HIGH)); ?> --EXPECTF-- -Deprecated: Constant FILTER_SANITIZE_STRING is deprecated in %s on line %d +Deprecated: Constant FILTER_SANITIZE_STRING is deprecated since 8.1, use htmlspecialchars() instead in %s on line %d string(0) "" string(0) "" string(0) "" diff --git a/ext/filter/tests/gh16993.phpt b/ext/filter/tests/gh16993.phpt new file mode 100644 index 0000000000000..c264296fc15e0 --- /dev/null +++ b/ext/filter/tests/gh16993.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-16993: filter_var_array should emit warning for unknown filters +--EXTENSIONS-- +filter +--FILE-- + '42']; + +$result = filter_var_array($data, ['test' => FILTER_VALIDATE_INT|FILTER_NULL_ON_FAILURE]); +var_dump($result); + +$result = filter_var_array($data, ['test' => ['filter' => FILTER_VALIDATE_INT, 'flags' => FILTER_NULL_ON_FAILURE]]); +var_dump($result); +?> +--EXPECTF-- +Warning: filter_var_array(): Unknown filter with ID 134217985 in %s on line %d +array(1) { + ["test"]=> + string(2) "42" +} +array(1) { + ["test"]=> + int(42) +} diff --git a/ext/filter/tests/throw-on-failure/filter_input_array_failure.phpt b/ext/filter/tests/throw-on-failure/filter_input_array_failure.phpt new file mode 100644 index 0000000000000..868829dbbac05 --- /dev/null +++ b/ext/filter/tests/throw-on-failure/filter_input_array_failure.phpt @@ -0,0 +1,29 @@ +--TEST-- +FILTER_THROW_ON_FAILURE: filter_input_array() failure +--EXTENSIONS-- +filter +--GET-- +a=1 +--FILE-- + ['flags' => FILTER_REQUIRE_ARRAY | FILTER_THROW_ON_FAILURE]]); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +echo "\nvalidation fails (filter value)\n"; +try { + filter_input_array(INPUT_GET, ['a' => ['filter' => FILTER_VALIDATE_EMAIL, 'flags' => FILTER_THROW_ON_FAILURE]]); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +validation fails (array type check) +Filter\FilterFailedException: filter validation failed: not an array (got string) + +validation fails (filter value) +Filter\FilterFailedException: filter validation failed: filter validate_email not satisfied by '1' diff --git a/ext/filter/tests/throw-on-failure/filter_input_failure.phpt b/ext/filter/tests/throw-on-failure/filter_input_failure.phpt new file mode 100644 index 0000000000000..8ec2d572e7f11 --- /dev/null +++ b/ext/filter/tests/throw-on-failure/filter_input_failure.phpt @@ -0,0 +1,39 @@ +--TEST-- +FILTER_THROW_ON_FAILURE: filter_input() failure +--EXTENSIONS-- +filter +--GET-- +a=1 +--FILE-- +getMessage() . "\n"; +} + +echo "\nvalidation fails (array type check)\n"; +try { + filter_input(INPUT_GET, 'a', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY | FILTER_THROW_ON_FAILURE); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +echo "\nvalidation fails (filter value)\n"; +try { + filter_input(INPUT_GET, 'a', FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +missing value +Filter\FilterFailedException: input value 'b' not found + +validation fails (array type check) +Filter\FilterFailedException: filter validation failed: not an array (got string) + +validation fails (filter value) +Filter\FilterFailedException: filter validation failed: filter validate_email not satisfied by '1' diff --git a/ext/filter/tests/throw-on-failure/filter_success.phpt b/ext/filter/tests/throw-on-failure/filter_success.phpt new file mode 100644 index 0000000000000..c5b0e2fc9fdd5 --- /dev/null +++ b/ext/filter/tests/throw-on-failure/filter_success.phpt @@ -0,0 +1,68 @@ +--TEST-- +FILTER_THROW_ON_FAILURE: successful filters do not throw +--EXTENSIONS-- +filter +--GET-- +a=daniel.e.scherzer@gmail.com +--FILE-- +wrapped; } +} + +echo "filter_input:\n"; +var_dump(filter_input(INPUT_GET, 'a', FILTER_DEFAULT, FILTER_THROW_ON_FAILURE)); +var_dump(filter_input(INPUT_GET, 'a', FILTER_DEFAULT, FILTER_REQUIRE_SCALAR | FILTER_THROW_ON_FAILURE)); +var_dump(filter_input(INPUT_GET, 'a', FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE)); + +echo "\nfilter_input_array:\n"; +var_dump(filter_input_array(INPUT_GET, ['a' => ['flags' => FILTER_REQUIRE_SCALAR | FILTER_THROW_ON_FAILURE]])); +var_dump(filter_input_array(INPUT_GET, ['a' => ['filter' => FILTER_VALIDATE_EMAIL, 'flags' => FILTER_THROW_ON_FAILURE]])); + +echo "\nfilter_var:\n"; +var_dump(filter_var('a', FILTER_DEFAULT, FILTER_REQUIRE_SCALAR | FILTER_THROW_ON_FAILURE)); +var_dump(filter_var(new MyString('daniel.e.scherzer@gmail.com'), FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE)); +var_dump(filter_var('daniel.e.scherzer@gmail.com', FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE)); + +echo "\nfilter_var_array:\n"; +var_dump(filter_var_array(['a' => 'a'], ['a' => ['flags' => FILTER_REQUIRE_SCALAR | FILTER_THROW_ON_FAILURE]])); +var_dump(filter_var_array(['a' => new MyString('bar')], ['a' => ['flags' => FILTER_THROW_ON_FAILURE]])); +var_dump(filter_var_array(['a' => 'daniel.e.scherzer@gmail.com'], ['a' => ['filter' => FILTER_VALIDATE_EMAIL, 'flags' => FILTER_THROW_ON_FAILURE]])); + +?> +--EXPECT-- +filter_input: +string(27) "daniel.e.scherzer@gmail.com" +string(27) "daniel.e.scherzer@gmail.com" +string(27) "daniel.e.scherzer@gmail.com" + +filter_input_array: +array(1) { + ["a"]=> + string(27) "daniel.e.scherzer@gmail.com" +} +array(1) { + ["a"]=> + string(27) "daniel.e.scherzer@gmail.com" +} + +filter_var: +string(1) "a" +string(27) "daniel.e.scherzer@gmail.com" +string(27) "daniel.e.scherzer@gmail.com" + +filter_var_array: +array(1) { + ["a"]=> + string(1) "a" +} +array(1) { + ["a"]=> + string(3) "bar" +} +array(1) { + ["a"]=> + string(27) "daniel.e.scherzer@gmail.com" +} diff --git a/ext/filter/tests/throw-on-failure/filter_var_array_failure.phpt b/ext/filter/tests/throw-on-failure/filter_var_array_failure.phpt new file mode 100644 index 0000000000000..f40dec1537dd8 --- /dev/null +++ b/ext/filter/tests/throw-on-failure/filter_var_array_failure.phpt @@ -0,0 +1,37 @@ +--TEST-- +FILTER_THROW_ON_FAILURE: filter_var_array() failure +--EXTENSIONS-- +filter +--FILE-- + 'a'], ['a' => ['flags' => FILTER_REQUIRE_ARRAY | FILTER_THROW_ON_FAILURE]]); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +echo "\nvalidation fails (object without __toString)\n"; +try { + filter_var_array(['a' => new stdClass()], ['a' => ['flags' => FILTER_THROW_ON_FAILURE]]); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +echo "\nvalidation fails (filter value)\n"; +try { + filter_var_array(['a' => true], ['a' => ['filter' => FILTER_VALIDATE_EMAIL, 'flags' => FILTER_THROW_ON_FAILURE]]); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +validation fails (array type check) +Filter\FilterFailedException: filter validation failed: not an array (got string) + +validation fails (object without __toString) +Filter\FilterFailedException: filter validation failed: object of type stdClass has no __toString() method + +validation fails (filter value) +Filter\FilterFailedException: filter validation failed: filter validate_email not satisfied by '1' diff --git a/ext/filter/tests/throw-on-failure/filter_var_failure.phpt b/ext/filter/tests/throw-on-failure/filter_var_failure.phpt new file mode 100644 index 0000000000000..fccc61da4d0ff --- /dev/null +++ b/ext/filter/tests/throw-on-failure/filter_var_failure.phpt @@ -0,0 +1,37 @@ +--TEST-- +FILTER_THROW_ON_FAILURE: filter_input() failure +--EXTENSIONS-- +filter +--FILE-- +getMessage() . "\n"; +} + +echo "\nvalidation fails (object without __toString)\n"; +try { + filter_var(new stdClass(), FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +echo "\nvalidation fails (filter value)\n"; +try { + filter_var('a', FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE); +} catch (Filter\FilterFailedException $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +validation fails (array type check) +Filter\FilterFailedException: filter validation failed: not an array (got string) + +validation fails (object without __toString) +Filter\FilterFailedException: filter validation failed: object of type stdClass has no __toString() method + +validation fails (filter value) +Filter\FilterFailedException: filter validation failed: filter validate_email not satisfied by 'a' diff --git a/ext/filter/tests/throw-on-failure/throw-and-null-error.phpt b/ext/filter/tests/throw-on-failure/throw-and-null-error.phpt new file mode 100644 index 0000000000000..48c37618ed917 --- /dev/null +++ b/ext/filter/tests/throw-on-failure/throw-and-null-error.phpt @@ -0,0 +1,86 @@ +--TEST-- +Cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE +--EXTENSIONS-- +filter +--GET-- +a=1 +--FILE-- +getMessage() . "\n"; +} +try { + filter_input(INPUT_GET, 'b', FILTER_DEFAULT, ['flags' => $flags]); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +echo "\nfilter_input(), with a missing value and a default\n"; +try { + filter_input(INPUT_GET, 'b', FILTER_DEFAULT, ['flags' => $flags, 'options' => ['default' => 'a']]); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +echo "\nfilter_input(), with a present value\n"; +try { + filter_input(INPUT_GET, 'a', FILTER_DEFAULT, $flags); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +try { + filter_input(INPUT_GET, 'a', FILTER_DEFAULT, ['flags' => $flags]); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +echo "\nfilter_var()\n"; +try { + filter_var(true, FILTER_DEFAULT, $flags); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +try { + filter_var(true, FILTER_DEFAULT, ['flags' => $flags]); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +echo "\nfilter_input_array()\n"; +try { + filter_input_array(INPUT_GET, ['a' => ['flags' => $flags]]); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} + +echo "\nfilter_var_array()\n"; +try { + filter_var_array(['a' => true], ['a' => ['flags' => $flags]]); +} catch (ValueError $e) { + echo get_class($e) . ": " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +filter_input(), with a missing value +ValueError: filter_input(): Argument #4 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE +ValueError: filter_input(): Argument #4 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE + +filter_input(), with a missing value and a default +ValueError: filter_input(): Argument #4 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE + +filter_input(), with a present value +ValueError: filter_input(): Argument #4 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE +ValueError: filter_input(): Argument #4 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE + +filter_var() +ValueError: filter_var(): Argument #3 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE +ValueError: filter_var(): Argument #3 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE + +filter_input_array() +ValueError: filter_input_array(): Argument #2 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE + +filter_var_array() +ValueError: filter_var_array(): Argument #2 ($options) cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index f37ee68617616..ceb3ee2509035 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -1382,7 +1382,8 @@ static int my_poll(php_socket_t fd, int events, int timeout) { if (n == -1 && php_socket_errno() == EINTR) { zend_hrtime_t delta_ns = zend_hrtime() - start_ns; - if (delta_ns > timeout_hr) { + /* delta_ns == 0 is only possible with a platform that does not support a high-res timer. */ + if (delta_ns > timeout_hr || UNEXPECTED(delta_ns == 0)) { #ifndef PHP_WIN32 errno = ETIMEDOUT; #endif diff --git a/ext/gd/config.m4 b/ext/gd/config.m4 index a95ea3fba70ec..0d024c9ea1cf3 100644 --- a/ext/gd/config.m4 +++ b/ext/gd/config.m4 @@ -65,6 +65,7 @@ AC_DEFUN([PHP_GD_PNG],[ PHP_EVAL_LIBLINE([$PNG_LIBS], [GD_SHARED_LIBADD]) PHP_EVAL_INCLINE([$PNG_CFLAGS]) AC_DEFINE([HAVE_LIBPNG], [1], [Define to 1 if you have the libpng library.]) + AC_DEFINE([HAVE_GD_PNG], [1], [Define to 1 if gd extension has PNG support.]) ]) AC_DEFUN([PHP_GD_AVIF], [ @@ -162,17 +163,22 @@ AC_CACHE_CHECK([for working gdImageCreateFrom$1 in libgd], [php_var], /* A custom gdErrorMethod */ void exit1(int priority, const char *format, va_list args) { + (void)priority; + (void)format; + (void)args; _exit(1); } /* Override the default gd_error_method with one that actually causes the program to return an error. */ -int main(int argc, char** argv) { +int main(void) +{ m4_if([$1],[Xpm], [char* f = "test.xpm"], [FILE* f = NULL]); gdSetErrorMethod(exit1); gdImagePtr p = gdImageCreateFrom$1(f); + (void)p; return 0; }])], [AS_VAR_SET([php_var], [yes])], @@ -191,8 +197,6 @@ AC_DEFUN([PHP_GD_CHECK_VERSION],[ PHP_GD_CHECK_FORMAT([Webp], [AC_DEFINE([HAVE_GD_WEBP], [1])]) PHP_GD_CHECK_FORMAT([Jpeg], [AC_DEFINE([HAVE_GD_JPG], [1])]) PHP_GD_CHECK_FORMAT([Xpm], [AC_DEFINE([HAVE_GD_XPM], [1])]) - PHP_GD_CHECK_FORMAT([Bmp], [AC_DEFINE([HAVE_GD_BMP], [1])]) - PHP_GD_CHECK_FORMAT([Tga], [AC_DEFINE([HAVE_GD_TGA], [1])]) PHP_CHECK_LIBRARY([gd], [gdFontCacheShutdown], [AC_DEFINE([HAVE_GD_FREETYPE], [1])], [], @@ -258,15 +262,8 @@ if test "$PHP_GD" != "no"; then libgd/wbmp.c "]) -dnl These are always available with bundled library AC_DEFINE([HAVE_GD_BUNDLED], [1], [Define to 1 if gd extension uses GD library bundled in PHP.]) - AC_DEFINE([HAVE_GD_PNG], [1], - [Define to 1 if gd extension has PNG support.]) - AC_DEFINE([HAVE_GD_BMP], [1], - [Define to 1 if gd extension has BMP support.]) - AC_DEFINE([HAVE_GD_TGA], [1], - [Define to 1 if gd extension has TGA support.]) dnl Various checks for GD features PHP_SETUP_ZLIB([GD_SHARED_LIBADD]) diff --git a/ext/gd/config.w32 b/ext/gd/config.w32 index b410db7f1cb37..a86693ad74bea 100644 --- a/ext/gd/config.w32 +++ b/ext/gd/config.w32 @@ -61,8 +61,6 @@ if (PHP_GD != "no") { gd_crop.c gd_interpolation.c gd_matrix.c gd_bmp.c gd_tga.c", "gd"); AC_DEFINE('HAVE_GD_BUNDLED', 1, "Define to 1 if gd extension uses GD library bundled in PHP."); AC_DEFINE('HAVE_GD_PNG', 1, "Define to 1 if gd extension has PNG support."); - AC_DEFINE('HAVE_GD_BMP', 1, "Define to 1 if gd extension has BMP support."); - AC_DEFINE('HAVE_GD_TGA', 1, "Define to 1 if gd extension has TGA support."); AC_DEFINE('HAVE_LIBPNG', 1, "Define to 1 if you have the libpng library."); AC_DEFINE('HAVE_LIBJPEG', 1, "Define to 1 if you have the libjpeg library."); AC_DEFINE('HAVE_GD_JPG', 1, "Define to 1 if gd extension has JPEG support."); diff --git a/ext/gd/gd.c b/ext/gd/gd.c index e993fb65f47d0..0b115d7e589ba 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -34,6 +34,7 @@ #include "ext/standard/info.h" #include "php_open_temporary_file.h" #include "php_memory_streams.h" +#include "zend_attributes.h" #include "zend_object_handlers.h" #ifdef HAVE_SYS_WAIT_H @@ -443,15 +444,11 @@ PHP_MINFO_FUNCTION(gd) #ifdef HAVE_GD_WEBP php_info_print_table_row(2, "WebP Support", "enabled"); #endif -#ifdef HAVE_GD_BMP php_info_print_table_row(2, "BMP Support", "enabled"); -#endif #ifdef HAVE_GD_AVIF php_info_print_table_row(2, "AVIF Support", "enabled"); #endif -#ifdef HAVE_GD_TGA php_info_print_table_row(2, "TGA Read Support", "enabled"); -#endif php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } @@ -496,21 +493,13 @@ PHP_FUNCTION(gd_info) #else add_assoc_bool(return_value, "WebP Support", 0); #endif -#ifdef HAVE_GD_BMP add_assoc_bool(return_value, "BMP Support", 1); -#else - add_assoc_bool(return_value, "BMP Support", 0); -#endif #ifdef HAVE_GD_AVIF add_assoc_bool(return_value, "AVIF Support", 1); #else add_assoc_bool(return_value, "AVIF Support", 0); #endif -#ifdef HAVE_GD_TGA add_assoc_bool(return_value, "TGA Read Support", 1); -#else - add_assoc_bool(return_value, "TGA Read Support", 0); -#endif #ifdef USE_GD_JISX0208 add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 1); #else @@ -830,6 +819,11 @@ PHP_FUNCTION(imagefilledellipse) Z_PARAM_LONG(color) ZEND_PARSE_PARAMETERS_END(); + if (w < 0 || ZEND_LONG_INT_OVFL(w)) { + zend_argument_value_error(4, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + im = php_gd_libgdimageptr_from_zval_p(IM); gdImageFilledEllipse(im, cx, cy, w, h, color); @@ -1335,12 +1329,8 @@ PHP_FUNCTION(imagetypes) #ifdef HAVE_GD_WEBP ret |= PHP_IMG_WEBP; #endif -#ifdef HAVE_GD_BMP ret |= PHP_IMG_BMP; -#endif -#ifdef HAVE_GD_TGA ret |= PHP_IMG_TGA; -#endif #ifdef HAVE_GD_AVIF ret |= PHP_IMG_AVIF; #endif @@ -1589,7 +1579,7 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, pefree(pstr, 1); zend_string_release_ex(buff, 0); } - else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO)) { + else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO) == SUCCESS) { /* try and force the stream to be FILE* */ if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void **) &fp, REPORT_ERRORS)) { goto out_err; @@ -1724,23 +1714,19 @@ PHP_FUNCTION(imagecreatefromgd2part) } /* }}} */ -#ifdef HAVE_GD_BMP /* {{{ Create a new image from BMP file or URL */ PHP_FUNCTION(imagecreatefrombmp) { _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_BMP, "BMP", gdImageCreateFromBmp, gdImageCreateFromBmpCtx); } /* }}} */ -#endif -#ifdef HAVE_GD_TGA /* {{{ Create a new image from TGA file or URL */ PHP_FUNCTION(imagecreatefromtga) { _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_TGA, "TGA", gdImageCreateFromTga, gdImageCreateFromTgaCtx); } /* }}} */ -#endif /* {{{ _php_image_output */ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn) @@ -2127,7 +2113,6 @@ PHP_FUNCTION(imagegd2) } /* }}} */ -#ifdef HAVE_GD_BMP /* {{{ Output BMP image to browser or file */ PHP_FUNCTION(imagebmp) { @@ -2158,7 +2143,6 @@ PHP_FUNCTION(imagebmp) RETURN_TRUE; } /* }}} */ -#endif /* {{{ Destroy an image - No effect as of PHP 8.0 */ PHP_FUNCTION(imagedestroy) diff --git a/ext/gd/gd.stub.php b/ext/gd/gd.stub.php index b3b82766ee981..0632724b44f38 100644 --- a/ext/gd/gd.stub.php +++ b/ext/gd/gd.stub.php @@ -449,17 +449,11 @@ * /usr/include/pngconf.h:310:2: error: #error png.h already includes setjmp.h with some additional fixup. * as error, use the values for now... */ -/** @var int */ const PNG_NO_FILTER = 0x00; -/** @var int */ const PNG_FILTER_NONE = 0x08; -/** @var int */ const PNG_FILTER_SUB = 0x10; -/** @var int */ const PNG_FILTER_UP = 0x20; -/** @var int */ const PNG_FILTER_AVG = 0x40; -/** @var int */ const PNG_FILTER_PAETH = 0x80; /** @var int */ const PNG_ALL_FILTERS = 0x08 | 0x10 | 0x20 | 0x40 | 0x80; @@ -589,14 +583,10 @@ function imagecreatefromgd2(string $filename): GdImage|false {} /** @refcount 1 */ function imagecreatefromgd2part(string $filename, int $x, int $y, int $width, int $height): GdImage|false {} -#ifdef HAVE_GD_BMP /** @refcount 1 */ function imagecreatefrombmp(string $filename): GdImage|false {} -#endif -#ifdef HAVE_GD_TGA function imagecreatefromtga(string $filename): GdImage|false {} -#endif function imagexbm(GdImage $image, ?string $filename, ?int $foreground_color = null): bool {} @@ -630,11 +620,10 @@ function imagegd(GdImage $image, ?string $file = null): bool {} function imagegd2(GdImage $image, ?string $file = null, int $chunk_size = 128, int $mode = IMG_GD2_RAW): bool {} -#ifdef HAVE_GD_BMP /** @param resource|string|null $file */ function imagebmp(GdImage $image, $file = null, bool $compressed = true): bool {} -#endif +#[\Deprecated(since: '8.5', message: "as it has no effect since PHP 8.0")] function imagedestroy(GdImage $image): true {} function imagecolorallocate(GdImage $image, int $red, int $green, int $blue): int|false {} diff --git a/ext/gd/gd_arginfo.h b/ext/gd/gd_arginfo.h index c80aaac463348..87cbfa54b945d 100644 --- a/ext/gd/gd_arginfo.h +++ b/ext/gd/gd_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 94822f6472750c646fc138f383278ca692b39d27 */ + * Stub hash: 2cdc0b485d9b62bb9021973d3c8cce0169b21ac0 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -191,17 +191,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_imagecreatefromgd2part, 0, 5 ZEND_ARG_TYPE_INFO(0, height, IS_LONG, 0) ZEND_END_ARG_INFO() -#if defined(HAVE_GD_BMP) -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_imagecreatefrombmp, 0, 1, GdImage, MAY_BE_FALSE) - ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) -ZEND_END_ARG_INFO() -#endif +#define arginfo_imagecreatefrombmp arginfo_imagecreatefromgif -#if defined(HAVE_GD_TGA) -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_imagecreatefromtga, 0, 1, GdImage, MAY_BE_FALSE) - ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) -ZEND_END_ARG_INFO() -#endif +#define arginfo_imagecreatefromtga arginfo_imagecreatefromgif ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagexbm, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) @@ -266,13 +258,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagegd2, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "IMG_GD2_RAW") ZEND_END_ARG_INFO() -#if defined(HAVE_GD_BMP) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagebmp, 0, 1, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, file, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, compressed, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagedestroy, 0, 1, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) @@ -619,12 +609,8 @@ ZEND_FUNCTION(imagecreatefromwbmp); ZEND_FUNCTION(imagecreatefromgd); ZEND_FUNCTION(imagecreatefromgd2); ZEND_FUNCTION(imagecreatefromgd2part); -#if defined(HAVE_GD_BMP) ZEND_FUNCTION(imagecreatefrombmp); -#endif -#if defined(HAVE_GD_TGA) ZEND_FUNCTION(imagecreatefromtga); -#endif ZEND_FUNCTION(imagexbm); #if defined(HAVE_GD_AVIF) ZEND_FUNCTION(imageavif); @@ -642,9 +628,7 @@ ZEND_FUNCTION(imagejpeg); ZEND_FUNCTION(imagewbmp); ZEND_FUNCTION(imagegd); ZEND_FUNCTION(imagegd2); -#if defined(HAVE_GD_BMP) ZEND_FUNCTION(imagebmp); -#endif ZEND_FUNCTION(imagedestroy); ZEND_FUNCTION(imagecolorallocate); ZEND_FUNCTION(imagepalettecopy); @@ -755,12 +739,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(imagecreatefromgd, arginfo_imagecreatefromgd) ZEND_FE(imagecreatefromgd2, arginfo_imagecreatefromgd2) ZEND_FE(imagecreatefromgd2part, arginfo_imagecreatefromgd2part) -#if defined(HAVE_GD_BMP) ZEND_FE(imagecreatefrombmp, arginfo_imagecreatefrombmp) -#endif -#if defined(HAVE_GD_TGA) ZEND_FE(imagecreatefromtga, arginfo_imagecreatefromtga) -#endif ZEND_FE(imagexbm, arginfo_imagexbm) #if defined(HAVE_GD_AVIF) ZEND_FE(imageavif, arginfo_imageavif) @@ -778,10 +758,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(imagewbmp, arginfo_imagewbmp) ZEND_FE(imagegd, arginfo_imagegd) ZEND_FE(imagegd2, arginfo_imagegd2) -#if defined(HAVE_GD_BMP) ZEND_FE(imagebmp, arginfo_imagebmp) -#endif - ZEND_FE(imagedestroy, arginfo_imagedestroy) + ZEND_RAW_FENTRY("imagedestroy", zif_imagedestroy, arginfo_imagedestroy, ZEND_ACC_DEPRECATED, NULL, NULL) ZEND_FE(imagecolorallocate, arginfo_imagecolorallocate) ZEND_FE(imagepalettecopy, arginfo_imagepalettecopy) ZEND_FE(imagecolorat, arginfo_imagecolorat) @@ -945,6 +923,14 @@ static void register_gd_symbols(int module_number) REGISTER_LONG_CONSTANT("PNG_FILTER_PAETH", 0x80, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PNG_ALL_FILTERS", 0x8 | 0x10 | 0x20 | 0x40 | 0x80, CONST_PERSISTENT); #endif + + + zend_attribute *attribute_Deprecated_func_imagedestroy_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "imagedestroy", sizeof("imagedestroy") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_imagedestroy_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_imagedestroy_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_imagedestroy_0_arg1_str = zend_string_init("as it has no effect since PHP 8.0", strlen("as it has no effect since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_func_imagedestroy_0->args[1].value, attribute_Deprecated_func_imagedestroy_0_arg1_str); + attribute_Deprecated_func_imagedestroy_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_GdImage(void) diff --git a/ext/gd/php_gd.h b/ext/gd/php_gd.h index 8d27f8cc75a60..1ef57cb3c4d94 100644 --- a/ext/gd/php_gd.h +++ b/ext/gd/php_gd.h @@ -23,7 +23,6 @@ #if defined(HAVE_LIBGD) || defined(HAVE_GD_BUNDLED) -/* open_basedir and safe_mode checks */ #define PHP_GD_CHECK_OPEN_BASEDIR(filename, errormsg) \ if (!filename || php_check_open_basedir(filename)) { \ php_error_docref(NULL, E_WARNING, errormsg); \ diff --git a/ext/gd/tests/bug19366.phpt b/ext/gd/tests/bug19366.phpt index 7fae0be5d7e0c..93288dc96adee 100644 --- a/ext/gd/tests/bug19366.phpt +++ b/ext/gd/tests/bug19366.phpt @@ -36,8 +36,6 @@ echo "Alive: Send to browser\n"; //Header("Content-type: image/PNG"); //ImagePNG($ImHandle); -echo "Alive: Free resources\n"; -imagedestroy($ImHandle); echo "Alive: Done\n"; ?> --EXPECT-- @@ -46,5 +44,4 @@ Alive: Define colors Alive: Draw Alive: ImageString Alive: Send to browser -Alive: Free resources Alive: Done diff --git a/ext/gd/tests/bug28147.phpt b/ext/gd/tests/bug28147.phpt index 90314b153225d..0578f659bd937 100644 --- a/ext/gd/tests/bug28147.phpt +++ b/ext/gd/tests/bug28147.phpt @@ -16,8 +16,6 @@ imagefilledrectangle($im,0,0,299,299,$w); imageantialias($im,true); imageline($im, 299, 299, 0, 299, $red); -imagedestroy($im); - echo "Alive\n"; ?> --EXPECT-- diff --git a/ext/gd/tests/bug36697-mb.phpt b/ext/gd/tests/bug36697-mb.phpt index 0a661012bcb04..f061076da72d2 100644 --- a/ext/gd/tests/bug36697-mb.phpt +++ b/ext/gd/tests/bug36697-mb.phpt @@ -13,7 +13,7 @@ imagecolortransparent($im, $trans_color); imagefilledrectangle($im, 0,0, 192,36, $trans_color); $c = imagecolorat($im, 191,35); imagegif($im, $dest); -imagedestroy($im); +$im = null; $im = imagecreatefromgif($dest); $c = imagecolorat($im, 191, 35); $colors = imagecolorsforindex($im, $c); diff --git a/ext/gd/tests/bug36697.phpt b/ext/gd/tests/bug36697.phpt index ae6cc5bc64d15..838750ccf251e 100644 --- a/ext/gd/tests/bug36697.phpt +++ b/ext/gd/tests/bug36697.phpt @@ -13,7 +13,7 @@ imagecolortransparent($im, $trans_color); imagefilledrectangle($im, 0,0, 192,36, $trans_color); $c = imagecolorat($im, 191,35); imagegif($im, $dest); -imagedestroy($im); +$im = null; $im = imagecreatefromgif($dest); $c = imagecolorat($im, 191, 35); $colors = imagecolorsforindex($im, $c); diff --git a/ext/gd/tests/bug38179.phpt b/ext/gd/tests/bug38179.phpt index 17e9ed28406e5..1dee6687677dc 100644 --- a/ext/gd/tests/bug38179.phpt +++ b/ext/gd/tests/bug38179.phpt @@ -18,8 +18,6 @@ imagecopy($dst_tc, $src, 0,0, 0,0, imagesx($src), imagesy($src)); $p1 = imagecolorat($dst_tc, 3,3); printf("%X\n", $p1); - -imagedestroy($src); imagedestroy($dst_tc); ?> --EXPECT-- 46FF0000 diff --git a/ext/gd/tests/bug42434.phpt b/ext/gd/tests/bug42434.phpt index d7cca5ab6b34b..ddc6c8000d629 100644 --- a/ext/gd/tests/bug42434.phpt +++ b/ext/gd/tests/bug42434.phpt @@ -15,8 +15,6 @@ if (imagecolorat($im, 9, 0) == 0x000000) { } else { echo 'Bugged'; } - -imagedestroy($im); ?> --EXPECT-- DONE diff --git a/ext/gd/tests/bug43121.phpt b/ext/gd/tests/bug43121.phpt index 21550a03c88d4..81eb564a5e69c 100644 --- a/ext/gd/tests/bug43121.phpt +++ b/ext/gd/tests/bug43121.phpt @@ -17,8 +17,6 @@ $im_tile = ImageCreateFromGif(__DIR__ . "/bug43121.gif" ); ImageSetTile( $im, $im_tile ); ImageFill( $im, 0, 0, IMG_COLOR_TILED ); -ImageDestroy( $im ); - print "OK"; ?> --EXPECT-- diff --git a/ext/gd/tests/bug43828.phpt b/ext/gd/tests/bug43828.phpt index 8bc3f9bbcaf83..fd6620666f8d2 100644 --- a/ext/gd/tests/bug43828.phpt +++ b/ext/gd/tests/bug43828.phpt @@ -23,8 +23,6 @@ imagefilledarc($im, 49, 49, 99,99, 0 , 360, $color, IMG_ARC_PIE); include_once __DIR__ . '/func.inc'; test_image_equals_file(__DIR__ . '/bug43828.png', $im); - -imagedestroy($im); ?> --EXPECT-- The images are equal. diff --git a/ext/gd/tests/bug45799.phpt b/ext/gd/tests/bug45799.phpt index f7124ce5b9713..dc20efdbb9428 100644 --- a/ext/gd/tests/bug45799.phpt +++ b/ext/gd/tests/bug45799.phpt @@ -12,7 +12,6 @@ if (!(imagetypes() & IMG_PNG)) { --EXPECTF-- Warning: imagepng(): gd-png error: no colors in palette%win %s on line %d diff --git a/ext/gd/tests/bug50194.phpt b/ext/gd/tests/bug50194.phpt index 33d2400c46e80..860ac3d50532b 100644 --- a/ext/gd/tests/bug50194.phpt +++ b/ext/gd/tests/bug50194.phpt @@ -32,8 +32,6 @@ if (isset($matches[1]) && $matches[1] > 2000) { } else { echo "The images are similar.\n"; } - -imagedestroy($im); ?> --EXPECT-- The images are similar. diff --git a/ext/gd/tests/bug61221.phpt b/ext/gd/tests/bug61221.phpt index 97a90db045b3a..fa2d89cff34d2 100644 --- a/ext/gd/tests/bug61221.phpt +++ b/ext/gd/tests/bug61221.phpt @@ -15,7 +15,6 @@ imageline($img, 0, $imageh / 2, $imagew - 1, $imageh / 2, $redsolid); imagegammacorrect($img, 1, 1); $color = imagecolorat($img, 0, 0); var_dump($color === $blacktransparent); -imagedestroy($img); ?> --EXPECT-- bool(true) diff --git a/ext/gd/tests/bug65148.phpt b/ext/gd/tests/bug65148.phpt index 4dfa13ccaa92a..0d71655aad107 100644 --- a/ext/gd/tests/bug65148.phpt +++ b/ext/gd/tests/bug65148.phpt @@ -37,10 +37,8 @@ foreach ($interpolations as $name => $interpolation) { $t = imagecolorallocatealpha($img, 0, 0, 0, 127); $imgr = imagerotate($img, -5, $t); $results[$name] = array('x' => imagesx($imgr), 'y' => imagesy($imgr)); - imagedestroy($imgr); } -imagedestroy($img); print_r($results); ?> --EXPECT-- diff --git a/ext/gd/tests/bug67325.phpt b/ext/gd/tests/bug67325.phpt index b1e84242a4a3b..fe5602567f8a3 100644 --- a/ext/gd/tests/bug67325.phpt +++ b/ext/gd/tests/bug67325.phpt @@ -24,8 +24,6 @@ for ($i = 0; $i < 256; $i++) { } } var_dump($white); - -imagedestroy($im); ?> --EXPECT-- int(0) diff --git a/ext/gd/tests/bug67447.phpt b/ext/gd/tests/bug67447.phpt index e78e272ff2e7b..f8e4d20c794d4 100644 --- a/ext/gd/tests/bug67447.phpt +++ b/ext/gd/tests/bug67447.phpt @@ -10,8 +10,6 @@ $red = imagecolorallocate($image, 255, 0, 0); imagefill($image, 0, 0, $red); $cropped = imagecrop($image, ['x' => 0, 'y' => 0, 'width' => 250, 'height' => 250]); var_dump(imagecolorat($cropped, 249, 249) === $red); -imagedestroy($image); -imagedestroy($cropped); // palette $image = imagecreate(500, 500); @@ -20,8 +18,6 @@ $red = imagecolorallocate($image, 255, 0, 0); imagefill($image, 0, 0, $red); $cropped = imagecrop($image, ['x' => 0, 'y' => 0, 'width' => 250, 'height' => 250]); var_dump(imagecolorsforindex($cropped, imagecolorat($cropped, 249, 249))); -imagedestroy($image); -imagedestroy($cropped); ?> --EXPECT-- bool(true) diff --git a/ext/gd/tests/bug69024.phpt b/ext/gd/tests/bug69024.phpt index da80a5b609a87..d6eaa40a31f8a 100644 --- a/ext/gd/tests/bug69024.phpt +++ b/ext/gd/tests/bug69024.phpt @@ -6,7 +6,6 @@ gd --EXPECT-- diff --git a/ext/gd/tests/bug70102.phpt b/ext/gd/tests/bug70102.phpt index bfdcbd377a3a2..63a81f7cc46a0 100644 --- a/ext/gd/tests/bug70102.phpt +++ b/ext/gd/tests/bug70102.phpt @@ -19,7 +19,6 @@ $white = imagecolorallocate($im, 255, 255, 255); var_dump($white & 0xffffff); imagefilledrectangle($im, 0, 0, 7, 7, $white); imagewebp($im, $filename); -imagedestroy($im); $im = imagecreatefromwebp($filename); $color = imagecolorat($im, 4, 4); diff --git a/ext/gd/tests/bug72339.phpt b/ext/gd/tests/bug72339.phpt index 561a1b347b51a..c6c30c5020764 100644 --- a/ext/gd/tests/bug72339.phpt +++ b/ext/gd/tests/bug72339.phpt @@ -33,9 +33,6 @@ fclose($fh); $im = imagecreatefromgd2($fname); -if ($im) { - imagedestroy($im); -} unlink($fname); ?> diff --git a/ext/gd/tests/bug72709.phpt b/ext/gd/tests/bug72709.phpt index b0b4aa77bdf92..bc20d1bf58b84 100644 --- a/ext/gd/tests/bug72709.phpt +++ b/ext/gd/tests/bug72709.phpt @@ -14,7 +14,6 @@ catch (\Error $ex) { } imagesetpixel($im, 0, 0, IMG_COLOR_STYLED); -imagedestroy($im); ?> ====DONE==== --EXPECT-- diff --git a/ext/gd/tests/bug77198_auto.phpt b/ext/gd/tests/bug77198_auto.phpt index 9df67d7f2ff6b..5153ec4870a9d 100644 --- a/ext/gd/tests/bug77198_auto.phpt +++ b/ext/gd/tests/bug77198_auto.phpt @@ -39,9 +39,7 @@ for ($y = 0; $y < 8; $y++) { if ($color !== 0x000000) { printf("Pixel at %d, %d: unexpected color (%d)\n", $x, $y, $color); } - imagedestroy($cropped); } - imagedestroy($orig); } } diff --git a/ext/gd/tests/bug77198_threshold.phpt b/ext/gd/tests/bug77198_threshold.phpt index e164286afca5f..662ebbe75c04d 100644 --- a/ext/gd/tests/bug77198_threshold.phpt +++ b/ext/gd/tests/bug77198_threshold.phpt @@ -36,9 +36,7 @@ for ($y = 0; $y < 8; $y++) { if ($color !== 0x000000) { printf("Pixel at %d, %d: unexpected color (%d)\n", $x, $y, $color); } - imagedestroy($cropped); } - imagedestroy($orig); } } diff --git a/ext/gd/tests/bug77391.phpt b/ext/gd/tests/bug77391.phpt index 6f41d164ddcd3..6f07ce57da1a5 100644 --- a/ext/gd/tests/bug77391.phpt +++ b/ext/gd/tests/bug77391.phpt @@ -5,7 +5,6 @@ gd --SKIPIF-- --FILE-- getMessage() . "\n"; } -imagedestroy($im); +$im = null; $im = imagecreate(5,5); imagecolorallocate($im, 255, 0, 255); $c = imagecolorclosest($im, 255,0,255); print_r(imagecolorsforindex($im, $c)); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); for ($i=0; $i<255; $i++) imagecolorresolve($im, $i,0,0); @@ -46,7 +46,7 @@ print_r(imagecolorsforindex($im, $c)); $im = imagecreatetruecolor(5,5); $c = imagecolorclosestalpha($im, 255,0,255,100); printf("%X\n", $c); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); $c = imagecolorclosestalpha($im, 255,0,255,100); @@ -55,13 +55,13 @@ try { } catch (ValueError $exception) { echo $exception->getMessage() . "\n"; } -imagedestroy($im); +$im = null; $im = imagecreate(5,5); imagecolorallocatealpha($im, 255, 0, 255, 1); $c = imagecolorclosestalpha($im, 255,0,255,1); print_r(imagecolorsforindex($im, $c)); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); for ($i=0; $i<255; $i++) imagecolorresolvealpha($im, $i,0,0,1); diff --git a/ext/gd/tests/colorexact.phpt b/ext/gd/tests/colorexact.phpt index 361701c77d364..c28ad54d5016c 100644 --- a/ext/gd/tests/colorexact.phpt +++ b/ext/gd/tests/colorexact.phpt @@ -12,7 +12,7 @@ $c2 = imagecolorexactalpha($im, 255,0,255, 100); printf("%X\n", $c); printf("%X\n", $c2); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); $c = imagecolorallocate($im, 255,0,255); @@ -26,8 +26,6 @@ echo imagecolorexactalpha($im, 255,200,0,100) . "\n"; // unallocated index echo imagecolorexact($im, 12,12,12) . "\n"; - -imagedestroy($im); ?> --EXPECT-- FF00FF diff --git a/ext/gd/tests/colormatch.phpt b/ext/gd/tests/colormatch.phpt index 65b690ecd0153..fe22784c9942a 100644 --- a/ext/gd/tests/colormatch.phpt +++ b/ext/gd/tests/colormatch.phpt @@ -15,8 +15,6 @@ try { } echo "ok\n"; - -imagedestroy($im); ?> --EXPECT-- imagecolormatch(): Argument #2 ($image2) must have at least one color diff --git a/ext/gd/tests/colorresolve.phpt b/ext/gd/tests/colorresolve.phpt index 08daa4bb5f04a..595018e73dcda 100644 --- a/ext/gd/tests/colorresolve.phpt +++ b/ext/gd/tests/colorresolve.phpt @@ -8,12 +8,12 @@ gd $im = imagecreatetruecolor(5,5); $c = imagecolorresolve($im, 255,0,255); printf("%X\n", $c); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); $c = imagecolorresolve($im, 255,0,255); print_r(imagecolorsforindex($im, $c)); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); for ($i=0; $i<255; $i++) imagecolorresolve($im, $i,0,0); @@ -38,12 +38,12 @@ print_r(imagecolorsforindex($im, $c)); $im = imagecreatetruecolor(5,5); $c = imagecolorresolvealpha($im, 255,0,255, 100); printf("%X\n", $c); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); $c = imagecolorresolvealpha($im, 255,0,255,100); print_r(imagecolorsforindex($im, $c)); -imagedestroy($im); +$im = null; $im = imagecreate(5,5); for ($i=0; $i<255; $i++) imagecolorresolvealpha($im, $i,0,0,1); diff --git a/ext/gd/tests/copy.phpt b/ext/gd/tests/copy.phpt index 5f099090e6611..dc0b5ca1293ba 100644 --- a/ext/gd/tests/copy.phpt +++ b/ext/gd/tests/copy.phpt @@ -22,7 +22,8 @@ if ($p1 && $p2 && $p3) { echo "TC/TC: ok\n"; } -imagedestroy($src_tc); imagedestroy($dst_tc); +$src_tc = null; +$dst_tc = null; $src_tc = imagecreatetruecolor(5,5); @@ -46,7 +47,8 @@ $p3 = $c3['red'] == 0x00 && $c3['blue']==0x00 && $c3['green']==0xff; if ($p1 && $p2 && $p3) { echo "TC/P: ok\n"; } -imagedestroy($src_tc); imagedestroy($dst_tc); +$src_tc = null; +$dst_tc = null; diff --git a/ext/gd/tests/dashedlines.phpt b/ext/gd/tests/dashedlines.phpt index 11b2e83fad46a..552b2bfc2976e 100644 --- a/ext/gd/tests/dashedlines.phpt +++ b/ext/gd/tests/dashedlines.phpt @@ -26,7 +26,7 @@ $p5 = imagecolorat($im, 5,5) == $b; if ($p1 && $p2 && $p3 && $p4 && $p5) { echo "Horizontal: ok\n"; } -imagedestroy($im); +$im = null; $im = imagecreatetruecolor(6,6); imagefill($im, 0,0, 0xffffff); @@ -46,7 +46,7 @@ $p6 = imagecolorat($im, 2,5) == $b; if ($p1 && $p2 && $p3 && $p4 && $p5 && $p6) { echo "Vertical: ok\n"; } -imagedestroy($im); +$im = null; $im = imagecreatetruecolor(6,6); @@ -66,9 +66,6 @@ $p6 = imagecolorat($im, 5,5) == $b; if ($p1 && $p2 && $p3 && $p4 && $p5 && $p6) { echo "Diagonal: ok\n"; } -imagedestroy($im); - - ?> --EXPECT-- Horizontal: ok diff --git a/ext/gd/tests/gh16232.phpt b/ext/gd/tests/gh16232.phpt index 7f839d737bb5b..469ae633c5da2 100644 --- a/ext/gd/tests/gh16232.phpt +++ b/ext/gd/tests/gh16232.phpt @@ -9,10 +9,10 @@ $bad_webp = __DIR__ . "/gh16232.webp"; copy($good_webp, $bad_webp); var_dump(imagecreatefromwbmp($bad_webp)); $data = file_get_contents($bad_webp); -$data[3] = chr(-1); +$data[3] = chr(255); file_put_contents($bad_webp, $data); var_dump(imagecreatefromwbmp($bad_webp)); -$data[3] = chr(1000); +$data[3] = chr(232); file_put_contents($bad_webp, $data); var_dump(imagecreatefromwbmp($bad_webp)); unlink($bad_webp); diff --git a/ext/gd/tests/gh19578.phpt b/ext/gd/tests/gh19578.phpt new file mode 100644 index 0000000000000..15d10f752d0d4 --- /dev/null +++ b/ext/gd/tests/gh19578.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19578: imagefilledellipse underflow on width argument +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +try { + imagefilledellipse($src, 0, 0, -16, 254, 0); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +imagefilledellipse(): Argument #4 ($width) must be between 0 and %d +imagefilledellipse(): Argument #4 ($width) must be between 0 and %d diff --git a/ext/gd/tests/gh19578_32bits.phpt b/ext/gd/tests/gh19578_32bits.phpt new file mode 100644 index 0000000000000..2cb73a60987e2 --- /dev/null +++ b/ext/gd/tests/gh19578_32bits.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-19578: imagefilledellipse underflow on width argument +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- +getMessage(); +} +?> +--EXPECTF-- +imagefilledellipse(): Argument #4 ($width) must be between 0 and %d diff --git a/ext/gd/tests/imagebmp_basic.phpt b/ext/gd/tests/imagebmp_basic.phpt index 31a62e674a845..ff302a8b07426 100644 --- a/ext/gd/tests/imagebmp_basic.phpt +++ b/ext/gd/tests/imagebmp_basic.phpt @@ -2,10 +2,6 @@ imagebmp() - basic functionality --EXTENSIONS-- gd ---SKIPIF-- - --FILE-- --EXPECT-- int(0) diff --git a/ext/gd/tests/imagecolorset_basic.phpt b/ext/gd/tests/imagecolorset_basic.phpt index 7677b85948aa4..006202007fa26 100644 --- a/ext/gd/tests/imagecolorset_basic.phpt +++ b/ext/gd/tests/imagecolorset_basic.phpt @@ -28,7 +28,6 @@ imagecolorset($im, $bg, 0, 0, 255); imagepalettetotruecolor($im); include_once __DIR__ . '/func.inc'; test_image_equals_file(__DIR__ . '/imagecolorset_basic.png', $im); -imagedestroy($im); ?> --EXPECT-- The images are equal. diff --git a/ext/gd/tests/imagecolorstotal_basic.phpt b/ext/gd/tests/imagecolorstotal_basic.phpt index 8f90b05e235ff..b95275cd32491 100644 --- a/ext/gd/tests/imagecolorstotal_basic.phpt +++ b/ext/gd/tests/imagecolorstotal_basic.phpt @@ -17,9 +17,6 @@ $gif = __DIR__."/php.gif"; $im = imagecreatefromgif($gif); echo 'Total colors in image: ' . imagecolorstotal($im); - -// Free image -imagedestroy($im); ?> --EXPECT-- *** Testing imagecolorstotal() : basic functionality *** diff --git a/ext/gd/tests/imagecolourstotal_basic.phpt b/ext/gd/tests/imagecolourstotal_basic.phpt index 0c9fd763247b2..f66a68424850a 100644 --- a/ext/gd/tests/imagecolourstotal_basic.phpt +++ b/ext/gd/tests/imagecolourstotal_basic.phpt @@ -22,15 +22,13 @@ var_dump( imagecolorstotal( $img )); $bg = imagecolorallocate( $img, 255, 0, 0 ); $bg = imagecolorallocate( $img, 0, 0, 255 ); var_dump( imagecolorstotal( $img )); -imagedestroy( $img ); +$img = null; // Truecolor image $img = imagecreatetruecolor( 50, 50 ); var_dump( imagecolorstotal( $img ) ); $bg = imagecolorallocate( $img, 255, 255, 255 ); var_dump( imagecolorstotal( $img ) ); -imagedestroy( $img ); - ?> --EXPECT-- *** Testing imagecolorstotal() : basic functionality *** diff --git a/ext/gd/tests/imagecopyresampled_basic.phpt b/ext/gd/tests/imagecopyresampled_basic.phpt index 9fb1178e540ae..3f2f735272392 100644 --- a/ext/gd/tests/imagecopyresampled_basic.phpt +++ b/ext/gd/tests/imagecopyresampled_basic.phpt @@ -47,11 +47,6 @@ imagepng($image_sml, $dest_sml); list($width, $height) = getimagesize($dest_sml); echo "Size of copy: width=". $width . " height=" . $height . "\n"; - -imagedestroy($image_lge); -imagedestroy($image_sml); - - echo "Done\n"; ?> --CLEAN-- diff --git a/ext/gd/tests/imagecopyresampled_variation1.phpt b/ext/gd/tests/imagecopyresampled_variation1.phpt index 207344765565f..6c3fd021a1ac7 100644 --- a/ext/gd/tests/imagecopyresampled_variation1.phpt +++ b/ext/gd/tests/imagecopyresampled_variation1.phpt @@ -59,9 +59,6 @@ if (!($alpha >= EXP_ALPHA - 1 && $alpha <= EXP_ALPHA + 1)) { printf("alpha: expected roughly %d, got %d\n", EXP_ALPHA, $alpha); } -imagedestroy($copy); -imagedestroy($im); - echo 'DONE'; ?> --EXPECT-- diff --git a/ext/gd/tests/imagecreatefrombmp_basic.phpt b/ext/gd/tests/imagecreatefrombmp_basic.phpt index 4989e617b4719..da6fe1b97dae9 100644 --- a/ext/gd/tests/imagecreatefrombmp_basic.phpt +++ b/ext/gd/tests/imagecreatefrombmp_basic.phpt @@ -4,7 +4,6 @@ imagecreatefrombmp() - basic functionality gd --SKIPIF-- --CLEAN-- diff --git a/ext/gd/tests/imagedestroy_deprecated.phpt b/ext/gd/tests/imagedestroy_deprecated.phpt new file mode 100644 index 0000000000000..37c39fbfe271c --- /dev/null +++ b/ext/gd/tests/imagedestroy_deprecated.phpt @@ -0,0 +1,11 @@ +--TEST-- +imagedestroy() deprecation message +--EXTENSIONS-- +gd +--FILE-- + +--EXPECTF-- +Deprecated: Function imagedestroy() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d diff --git a/ext/gd/tests/imagefill_1.phpt b/ext/gd/tests/imagefill_1.phpt index d8631f73cc42a..113c1c984387b 100644 --- a/ext/gd/tests/imagefill_1.phpt +++ b/ext/gd/tests/imagefill_1.phpt @@ -18,7 +18,6 @@ $green = imagecolorallocate($im, 0,255,0); print_r(imagecolorat($im, 0,0)); imagefill($im, 0,0,$white + 3); print_r(imagecolorat($im, 0,0)); -imagedestroy($im); ?> --EXPECT-- 00 diff --git a/ext/gd/tests/imagefilledpolygon_basic.phpt b/ext/gd/tests/imagefilledpolygon_basic.phpt index bbb8f9c2eb044..3681d96c6e73f 100644 --- a/ext/gd/tests/imagefilledpolygon_basic.phpt +++ b/ext/gd/tests/imagefilledpolygon_basic.phpt @@ -55,9 +55,6 @@ $color2 = imagecolorsforindex($image_in, $col2); $color3 = imagecolorsforindex($image_in, $col3); var_dump($color1, $color2, $color3); -imagedestroy($image); -imagedestroy($image_in); - echo "Done\n"; ?> --CLEAN-- diff --git a/ext/gd/tests/imagefttext.phpt b/ext/gd/tests/imagefttext.phpt index a60c4d8afbae6..83243a78e5205 100644 --- a/ext/gd/tests/imagefttext.phpt +++ b/ext/gd/tests/imagefttext.phpt @@ -40,11 +40,10 @@ gd $im = imagecreate(256, 256); var_dump(testrun($im, $fontfile_8859)); - imagedestroy($im); + $im = null; $im = imagecreatetruecolor(256, 256); var_dump(testrun($im, $fontfile_8859)); - imagedestroy($im); ?> --EXPECT-- bool(true) diff --git a/ext/gd/tests/imagepalettetotruecolor_basic.phpt b/ext/gd/tests/imagepalettetotruecolor_basic.phpt index e4e4ee89ca1d3..d886227a15ef8 100644 --- a/ext/gd/tests/imagepalettetotruecolor_basic.phpt +++ b/ext/gd/tests/imagepalettetotruecolor_basic.phpt @@ -11,7 +11,6 @@ var_dump($im instanceof GdImage); var_dump(imageistruecolor($im)); var_dump(imagepalettetotruecolor($im)); var_dump(imageistruecolor($im)); -imagedestroy($im); ?> --EXPECT-- bool(true) diff --git a/ext/gd/tests/imagepolygon_basic.phpt b/ext/gd/tests/imagepolygon_basic.phpt index c41b0710ef435..741f34c48ab83 100644 --- a/ext/gd/tests/imagepolygon_basic.phpt +++ b/ext/gd/tests/imagepolygon_basic.phpt @@ -42,8 +42,6 @@ $color1 = imagecolorsforindex($image, $col1); $color2 = imagecolorsforindex($image, $col2); var_dump($color1, $color2); -imagedestroy($image); - echo "Done\n"; ?> --CLEAN-- diff --git a/ext/gd/tests/imagerotate_overflow.phpt b/ext/gd/tests/imagerotate_overflow.phpt index a7be335ca92a6..590f4d7152c9d 100644 --- a/ext/gd/tests/imagerotate_overflow.phpt +++ b/ext/gd/tests/imagerotate_overflow.phpt @@ -11,14 +11,6 @@ $tmp = imagerotate ($im, 5, -9999999); var_dump($tmp); -if ($tmp) { - imagedestroy($tmp); -} - -if ($im) { - imagedestroy($im); -} - ?> --EXPECT-- bool(false) diff --git a/ext/gd/tests/imagettftext_charmap_order.phpt b/ext/gd/tests/imagettftext_charmap_order.phpt index 32d5c9d0d7e47..6fe5353e9fc26 100644 --- a/ext/gd/tests/imagettftext_charmap_order.phpt +++ b/ext/gd/tests/imagettftext_charmap_order.phpt @@ -61,7 +61,6 @@ if ($black_pixels >= 10) { } else { printf("FAIL %d black pixels\n", $black_pixels); } -imagedestroy($im); ?> --EXPECTF-- SUCCESS %d black pixels diff --git a/ext/gd/tests/libgd00100.phpt b/ext/gd/tests/libgd00100.phpt index 80e24d0ba203e..8f9955640b3c8 100644 --- a/ext/gd/tests/libgd00100.phpt +++ b/ext/gd/tests/libgd00100.phpt @@ -109,8 +109,6 @@ imagefilledpolygon($im, $points, $black); include_once __DIR__ . '/func.inc'; test_image_equals_file(__DIR__ . '/libgd00100.png', $im); - -imagedestroy($im); ?> --EXPECT-- The images are equal. diff --git a/ext/gd/tests/libgd00186.phpt b/ext/gd/tests/libgd00186.phpt index fb9e2985ced48..142f1637b2b30 100644 --- a/ext/gd/tests/libgd00186.phpt +++ b/ext/gd/tests/libgd00186.phpt @@ -26,8 +26,6 @@ if ($arr['blue'] == 2) { } else { $r = "Failed"; } -imagedestroy($tile); -imagedestroy($im); echo $r; ?> --EXPECT-- diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index 27f0dfa26da70..6badea4a17698 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -194,7 +194,7 @@ PHP_FUNCTION(bindtextdomain) btd_result = bindtextdomain(ZSTR_VAL(domain), NULL); if (btd_result == NULL) { /* POSIX-compliant implementations can return - * NULL if an error occured. On musl you will + * NULL if an error occurred. On musl you will * also get NULL if the domain is not yet * bound, because musl has no default directory * to return in that case. */ diff --git a/ext/hash/config.m4 b/ext/hash/config.m4 index 5248786efb084..2da44c503a62e 100644 --- a/ext/hash/config.m4 +++ b/ext/hash/config.m4 @@ -23,8 +23,7 @@ AS_VAR_IF([ac_cv_c_bigendian_php], [yes], [ SHA3_OPT_SRC="$SHA3_DIR/KeccakP-1600-inplace32BI.c" dnl Add -Wno-implicit-fallthrough flag as it happens on 32 bit builds AX_CHECK_COMPILE_FLAG([-Wno-implicit-fallthrough], - [PHP_HASH_CFLAGS="$PHP_HASH_CFLAGS -Wno-implicit-fallthrough"],, - [-Werror]) + [PHP_HASH_CFLAGS="$PHP_HASH_CFLAGS -Wno-implicit-fallthrough"]) ],[ AC_MSG_RESULT([yes]) SHA3_DIR="sha3/generic64lc" diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 13c345de4dd1c..ec5391a623049 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -229,20 +229,20 @@ static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) { significant bits first. This allows 32-bit and 64-bit architectures to interchange serialized HashContexts. */ -PHP_HASH_API zend_result php_hash_serialize_spec(const php_hashcontext_object *hash, zval *zv, const char *spec) /* {{{ */ +PHP_HASH_API hash_spec_result php_hash_serialize_spec(const php_hashcontext_object *hash, zval *zv, const char *spec) /* {{{ */ { size_t pos = 0, max_alignment = 1; unsigned char *buf = (unsigned char *) hash->context; zval tmp; if (buf == NULL) { - return FAILURE; + return HASH_SPEC_FAILURE; } array_init(zv); while (*spec != '\0' && *spec != '.') { char spec_ch = *spec; size_t sz, count = parse_serialize_spec(&spec, &pos, &sz, &max_alignment); if (pos + count * sz > hash->ops->context_size) { - return FAILURE; + return HASH_SPEC_FAILURE; } if (isupper((unsigned char) spec_ch)) { pos += count * sz; @@ -265,38 +265,33 @@ PHP_HASH_API zend_result php_hash_serialize_spec(const php_hashcontext_object *h } } if (*spec == '.' && align_to(pos, max_alignment) != hash->ops->context_size) { - return FAILURE; + return HASH_SPEC_FAILURE; } - return SUCCESS; + return HASH_SPEC_SUCCESS; } /* }}} */ -/* Unserialize a hash context serialized by `php_hash_serialize_spec` with `spec`. - Returns SUCCESS on success and a negative error code on failure. - Codes: FAILURE (-1) == generic failure - -999 == spec wrong size for context - -1000 - POS == problem at byte offset POS */ - -PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec) /* {{{ */ +/* Unserialize a hash context serialized by `php_hash_serialize_spec` with `spec`. */ +PHP_HASH_API hash_spec_result php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec) /* {{{ */ { size_t pos = 0, max_alignment = 1, j = 0; unsigned char *buf = (unsigned char *) hash->context; zval *elt; if (Z_TYPE_P(zv) != IS_ARRAY) { - return FAILURE; + return HASH_SPEC_FAILURE; } while (*spec != '\0' && *spec != '.') { char spec_ch = *spec; size_t sz, count = parse_serialize_spec(&spec, &pos, &sz, &max_alignment); if (pos + count * sz > hash->ops->context_size) { - return -999; + return WRONG_CONTEXT_SIZE; } if (isupper((unsigned char) spec_ch)) { pos += count * sz; } else if (sz == 1 && count > 1) { elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); if (!elt || Z_TYPE_P(elt) != IS_STRING || Z_STRLEN_P(elt) != count) { - return -1000 - pos; + return BYTE_OFFSET_POS_ERROR - pos; } ++j; memcpy(buf + pos, Z_STRVAL_P(elt), count); @@ -306,14 +301,14 @@ PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const z uint64_t val; elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); if (!elt || Z_TYPE_P(elt) != IS_LONG) { - return -1000 - pos; + return BYTE_OFFSET_POS_ERROR - pos; } ++j; val = (uint32_t) Z_LVAL_P(elt); if (sz == 8) { elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); if (!elt || Z_TYPE_P(elt) != IS_LONG) { - return -1000 - pos; + return BYTE_OFFSET_POS_ERROR - pos; } ++j; val += ((uint64_t) Z_LVAL_P(elt)) << 32; @@ -325,31 +320,32 @@ PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const z } } if (*spec == '.' && align_to(pos, max_alignment) != hash->ops->context_size) { - return -999; + return WRONG_CONTEXT_SIZE; } - return SUCCESS; + + return HASH_SPEC_SUCCESS; } /* }}} */ -PHP_HASH_API zend_result php_hash_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) /* {{{ */ +PHP_HASH_API hash_spec_result php_hash_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) /* {{{ */ { - if (hash->ops->serialize_spec) { - *magic = PHP_HASH_SERIALIZE_MAGIC_SPEC; - return php_hash_serialize_spec(hash, zv, hash->ops->serialize_spec); - } else { - return FAILURE; - } + if (!hash->ops->serialize_spec) { + return HASH_SPEC_FAILURE; + } + + *magic = PHP_HASH_SERIALIZE_MAGIC_SPEC; + return php_hash_serialize_spec(hash, zv, hash->ops->serialize_spec); } /* }}} */ -PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) /* {{{ */ +PHP_HASH_API hash_spec_result php_hash_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) /* {{{ */ { if (hash->ops->serialize_spec && magic == PHP_HASH_SERIALIZE_MAGIC_SPEC) { return php_hash_unserialize_spec(hash, zv, hash->ops->serialize_spec); - } else { - return FAILURE; } + + return HASH_SPEC_FAILURE; } /* }}} */ @@ -411,7 +407,7 @@ static void php_hash_do_hash( php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops->digest_size); ZSTR_VAL(hex_digest)[2 * ops->digest_size] = 0; - zend_string_release_ex(digest, 0); + zend_string_efree(digest); RETURN_NEW_STR(hex_digest); } } @@ -542,7 +538,7 @@ static void php_hash_do_hash_hmac( if (n < 0) { efree(context); efree(K); - zend_string_release(digest); + zend_string_efree(digest); RETURN_FALSE; } @@ -568,7 +564,7 @@ static void php_hash_do_hash_hmac( php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops->digest_size); ZSTR_VAL(hex_digest)[2 * ops->digest_size] = 0; - zend_string_release_ex(digest, 0); + zend_string_efree(digest); RETURN_NEW_STR(hex_digest); } } @@ -829,7 +825,7 @@ PHP_FUNCTION(hash_final) php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), digest_len); ZSTR_VAL(hex_digest)[2 * digest_len] = 0; - zend_string_release_ex(digest, 0); + zend_string_efree(digest); RETURN_NEW_STR(hex_digest); } } @@ -851,8 +847,6 @@ PHP_FUNCTION(hash_copy) RETVAL_OBJ(Z_OBJ_HANDLER_P(zhash, clone_obj)(Z_OBJ_P(zhash))); if (php_hashcontext_from_object(Z_OBJ_P(return_value))->context == NULL) { - zval_ptr_dtor(return_value); - zend_throw_error(NULL, "Cannot copy hash"); RETURN_THROWS(); } @@ -1184,6 +1178,7 @@ static void mhash_init(INIT_FUNC_ARGS) int len; int algo_number = 0; + zend_string *deprecation_reason = zend_string_init("as the mhash*() functions were deprecated", strlen("as the mhash*() functions were deprecated"), 1); for (algo_number = 0; algo_number < MHASH_NUM_ALGOS; algo_number++) { struct mhash_bc_entry algorithm = mhash_to_hash[algo_number]; if (algorithm.mhash_name == NULL) { @@ -1191,8 +1186,18 @@ static void mhash_init(INIT_FUNC_ARGS) } len = slprintf(buf, 127, "MHASH_%s", algorithm.mhash_name); - zend_register_long_constant(buf, len, algorithm.value, CONST_PERSISTENT|CONST_DEPRECATED, module_number); + zend_constant *mhash_const = zend_register_long_constant(buf, len, algorithm.value, CONST_PERSISTENT|CONST_DEPRECATED, module_number); + + zend_attribute *deprecation_attrib = zend_add_global_constant_attribute(mhash_const, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&deprecation_attrib->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + deprecation_attrib->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&deprecation_attrib->args[1].value, deprecation_reason); + deprecation_attrib->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } + /* Each of the attributes uses ZVAL_STR_COPY instead of trying to special + * case one of them to use ZVAL_STR, but that means there is one more + * reference that needs to be decremented. */ + zend_string_release(deprecation_reason); /* TODO: this cause #69823 zend_register_internal_module(&mhash_module_entry); */ } @@ -1477,7 +1482,7 @@ PHP_METHOD(HashContext, __serialize) ZVAL_LONG(&tmp, hash->options); zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); - if (hash->ops->hash_serialize(hash, &magic, &tmp) != SUCCESS) { + if (hash->ops->hash_serialize(hash, &magic, &tmp) != HASH_SPEC_SUCCESS) { goto serialize_failure; } zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); @@ -1506,7 +1511,7 @@ PHP_METHOD(HashContext, __unserialize) HashTable *data; zval *algo_zv, *magic_zv, *options_zv, *hash_zv, *members_zv; zend_long magic, options; - int unserialize_result; + hash_spec_result unserialize_result; const php_hash_ops *ops; if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &data) == FAILURE) { @@ -1555,7 +1560,7 @@ PHP_METHOD(HashContext, __unserialize) ops->hash_init(hash->context, NULL); unserialize_result = ops->hash_unserialize(hash, magic, hash_zv); - if (unserialize_result != SUCCESS) { + if (unserialize_result != HASH_SPEC_SUCCESS) { zend_throw_exception_ex(NULL, 0, "Incomplete or ill-formed serialization data (\"%s\" code %d)", ops->algo, unserialize_result); /* free context */ php_hashcontext_dtor(Z_OBJ_P(object)); diff --git a/ext/hash/hash_arginfo.h b/ext/hash/hash_arginfo.h index 24a17fd9750b4..0fb4407221af4 100644 --- a/ext/hash/hash_arginfo.h +++ b/ext/hash/hash_arginfo.h @@ -209,38 +209,23 @@ static void register_hash_symbols(int module_number) #if defined(PHP_MHASH_BC) zend_attribute *attribute_Deprecated_func_mhash_get_block_size_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mhash_get_block_size", sizeof("mhash_get_block_size") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_mhash_get_block_size_0_arg0; - zend_string *attribute_Deprecated_func_mhash_get_block_size_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_mhash_get_block_size_0_arg0, attribute_Deprecated_func_mhash_get_block_size_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mhash_get_block_size_0->args[0].value, &attribute_Deprecated_func_mhash_get_block_size_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mhash_get_block_size_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_mhash_get_block_size_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_mhash_get_hash_name_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mhash_get_hash_name", sizeof("mhash_get_hash_name") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_mhash_get_hash_name_0_arg0; - zend_string *attribute_Deprecated_func_mhash_get_hash_name_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_mhash_get_hash_name_0_arg0, attribute_Deprecated_func_mhash_get_hash_name_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mhash_get_hash_name_0->args[0].value, &attribute_Deprecated_func_mhash_get_hash_name_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mhash_get_hash_name_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_mhash_get_hash_name_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_mhash_keygen_s2k_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mhash_keygen_s2k", sizeof("mhash_keygen_s2k") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_mhash_keygen_s2k_0_arg0; - zend_string *attribute_Deprecated_func_mhash_keygen_s2k_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_mhash_keygen_s2k_0_arg0, attribute_Deprecated_func_mhash_keygen_s2k_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mhash_keygen_s2k_0->args[0].value, &attribute_Deprecated_func_mhash_keygen_s2k_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mhash_keygen_s2k_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_mhash_keygen_s2k_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_mhash_count_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mhash_count", sizeof("mhash_count") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_mhash_count_0_arg0; - zend_string *attribute_Deprecated_func_mhash_count_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_mhash_count_0_arg0, attribute_Deprecated_func_mhash_count_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mhash_count_0->args[0].value, &attribute_Deprecated_func_mhash_count_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mhash_count_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_mhash_count_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_mhash_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mhash", sizeof("mhash") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_mhash_0_arg0; - zend_string *attribute_Deprecated_func_mhash_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_mhash_0_arg0, attribute_Deprecated_func_mhash_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mhash_0->args[0].value, &attribute_Deprecated_func_mhash_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mhash_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_mhash_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); #endif } diff --git a/ext/hash/hash_gost.c b/ext/hash/hash_gost.c index 2ad6948a9a676..bba585a11f9fb 100644 --- a/ext/hash/hash_gost.c +++ b/ext/hash/hash_gost.c @@ -304,17 +304,17 @@ PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context) ZEND_SECURE_ZERO(context, sizeof(*context)); } -static int php_gost_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +static hash_spec_result php_gost_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) { PHP_GOST_CTX *ctx = (PHP_GOST_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_GOST_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_GOST_SPEC)) == HASH_SPEC_SUCCESS && ctx->length < sizeof(ctx->buffer)) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } const php_hash_ops php_hash_gost_ops = { diff --git a/ext/hash/hash_md.c b/ext/hash/hash_md.c index 96da7fce82a27..dd299e695891a 100644 --- a/ext/hash/hash_md.c +++ b/ext/hash/hash_md.c @@ -47,7 +47,7 @@ const php_hash_ops php_hash_md4_ops = { 1 }; -static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv); +static hash_spec_result php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv); const php_hash_ops php_hash_md2_ops = { "md2", @@ -356,15 +356,15 @@ PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context) memcpy(output, context->state, 16); } -static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +static hash_spec_result php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) { PHP_MD2_CTX *ctx = (PHP_MD2_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_MD2_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_MD2_SPEC)) == HASH_SPEC_SUCCESS && (unsigned char) ctx->in_buffer < sizeof(ctx->buffer)) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } diff --git a/ext/hash/hash_sha3.c b/ext/hash/hash_sha3.c index 07da2cfd2d016..8fa0a4b4e522b 100644 --- a/ext/hash/hash_sha3.c +++ b/ext/hash/hash_sha3.c @@ -200,20 +200,20 @@ static void PHP_SHA3_Final(unsigned char* digest, ZEND_SECURE_ZERO(ctx, sizeof(PHP_SHA3_CTX)); } -static int php_sha3_unserialize(php_hashcontext_object *hash, +static hash_spec_result php_sha3_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv, size_t block_size) { PHP_SHA3_CTX *ctx = (PHP_SHA3_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_SHA3_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_SHA3_SPEC)) == HASH_SPEC_SUCCESS && ctx->pos < block_size) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } // ========================================================================== @@ -292,23 +292,23 @@ const php_hash_ops php_hash_sha3_##bits##_ops = { \ #endif #define PHP_KECCAK_SPEC "b200IiIIB" -static zend_result php_keccak_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) +static hash_spec_result php_keccak_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) { *magic = PHP_HASH_SERIALIZE_MAGIC_KECCAK; return php_hash_serialize_spec(hash, zv, PHP_KECCAK_SPEC); } -static int php_keccak_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +static hash_spec_result php_keccak_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) { Keccak_HashInstance *ctx = (Keccak_HashInstance *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_KECCAK - && (r = php_hash_unserialize_spec(hash, zv, PHP_KECCAK_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_KECCAK_SPEC)) == HASH_SPEC_SUCCESS && ctx->sponge.byteIOIndex < ctx->sponge.rate / 8) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } // ========================================================================== diff --git a/ext/hash/hash_snefru.c b/ext/hash/hash_snefru.c index c1dbc3ae57a6c..b9b70f364208c 100644 --- a/ext/hash/hash_snefru.c +++ b/ext/hash/hash_snefru.c @@ -189,17 +189,17 @@ PHP_HASH_API void PHP_SNEFRUFinal(unsigned char digest[32], PHP_SNEFRU_CTX *cont ZEND_SECURE_ZERO(context, sizeof(*context)); } -static int php_snefru_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +static hash_spec_result php_snefru_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) { PHP_SNEFRU_CTX *ctx = (PHP_SNEFRU_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_SNEFRU_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_SNEFRU_SPEC)) == HASH_SPEC_SUCCESS && ctx->length < sizeof(ctx->buffer)) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } const php_hash_ops php_hash_snefru_ops = { diff --git a/ext/hash/hash_tiger.c b/ext/hash/hash_tiger.c index 841693a67dd14..62d1b7347143b 100644 --- a/ext/hash/hash_tiger.c +++ b/ext/hash/hash_tiger.c @@ -239,17 +239,17 @@ PHP_HASH_API void PHP_TIGER192Final(unsigned char digest[24], PHP_TIGER_CTX *con ZEND_SECURE_ZERO(context, sizeof(*context)); } -static int php_tiger_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +static hash_spec_result php_tiger_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) { PHP_TIGER_CTX *ctx = (PHP_TIGER_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_TIGER_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_TIGER_SPEC)) == HASH_SPEC_SUCCESS && ctx->length < sizeof(ctx->buffer)) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } #define PHP_HASH_TIGER_OPS(p, b) \ diff --git a/ext/hash/hash_whirlpool.c b/ext/hash/hash_whirlpool.c index db5a0da1236ad..fa3c216a64c4b 100644 --- a/ext/hash/hash_whirlpool.c +++ b/ext/hash/hash_whirlpool.c @@ -429,20 +429,20 @@ PHP_HASH_API void PHP_WHIRLPOOLFinal(unsigned char digest[64], PHP_WHIRLPOOL_CTX ZEND_SECURE_ZERO(context, sizeof(*context)); } -static int php_whirlpool_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +static hash_spec_result php_whirlpool_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) { PHP_WHIRLPOOL_CTX *ctx = (PHP_WHIRLPOOL_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_WHIRLPOOL_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_WHIRLPOOL_SPEC)) == HASH_SPEC_SUCCESS && ctx->buffer.pos >= 0 && ctx->buffer.pos < (int) sizeof(ctx->buffer.data) && ctx->buffer.bits >= ctx->buffer.pos * 8 && ctx->buffer.bits < ctx->buffer.pos * 8 + 8) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } const php_hash_ops php_hash_whirlpool_ops = { diff --git a/ext/hash/hash_xxhash.c b/ext/hash/hash_xxhash.c index 1c1315afd4b28..add922e8e84f7 100644 --- a/ext/hash/hash_xxhash.c +++ b/ext/hash/hash_xxhash.c @@ -17,9 +17,9 @@ #include "php_hash.h" #include "php_hash_xxhash.h" -static int php_hash_xxh32_unserialize( +static hash_spec_result php_hash_xxh32_unserialize( php_hashcontext_object *hash, zend_long magic, const zval *zv); -static int php_hash_xxh64_unserialize( +static hash_spec_result php_hash_xxh64_unserialize( php_hashcontext_object *hash, zend_long magic, const zval *zv); const php_hash_ops php_hash_xxh32_ops = { @@ -75,18 +75,18 @@ PHP_HASH_API zend_result PHP_XXH32Copy(const php_hash_ops *ops, const PHP_XXH32_ return SUCCESS; } -static int php_hash_xxh32_unserialize( +static hash_spec_result php_hash_xxh32_unserialize( php_hashcontext_object *hash, zend_long magic, const zval *zv) { PHP_XXH32_CTX *ctx = (PHP_XXH32_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_XXH32_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_XXH32_SPEC)) == HASH_SPEC_SUCCESS && ctx->s.memsize < 16) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } const php_hash_ops php_hash_xxh64_ops = { @@ -231,18 +231,18 @@ PHP_HASH_API zend_result PHP_XXH3_64_Copy(const php_hash_ops *ops, const PHP_XXH return SUCCESS; } -static int php_hash_xxh64_unserialize( +static hash_spec_result php_hash_xxh64_unserialize( php_hashcontext_object *hash, zend_long magic, const zval *zv) { PHP_XXH64_CTX *ctx = (PHP_XXH64_CTX *) hash->context; - int r = FAILURE; + hash_spec_result r = HASH_SPEC_FAILURE; if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC - && (r = php_hash_unserialize_spec(hash, zv, PHP_XXH64_SPEC)) == SUCCESS + && (r = php_hash_unserialize_spec(hash, zv, PHP_XXH64_SPEC)) == HASH_SPEC_SUCCESS && ctx->s.memsize < 32) { - return SUCCESS; - } else { - return r != SUCCESS ? r : -2000; + return HASH_SPEC_SUCCESS; } + + return r != HASH_SPEC_SUCCESS ? r : CONTEXT_VALIDATION_FAILURE; } const php_hash_ops php_hash_xxh3_128_ops = { diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h index 3b058ef48bdb2..f56605a33be6a 100644 --- a/ext/hash/php_hash.h +++ b/ext/hash/php_hash.h @@ -29,14 +29,22 @@ #define L64 INT64_C +typedef enum { + HASH_SPEC_SUCCESS = 0, + HASH_SPEC_FAILURE = -1, + WRONG_CONTEXT_SIZE = -999, + BYTE_OFFSET_POS_ERROR = -1000, + CONTEXT_VALIDATION_FAILURE = -2000, +} hash_spec_result; + typedef struct _php_hashcontext_object php_hashcontext_object; typedef void (*php_hash_init_func_t)(void *context, HashTable *args); typedef void (*php_hash_update_func_t)(void *context, const unsigned char *buf, size_t count); typedef void (*php_hash_final_func_t)(unsigned char *digest, void *context); typedef zend_result (*php_hash_copy_func_t)(const void *ops, const void *orig_context, void *dest_context); -typedef zend_result (*php_hash_serialize_func_t)(const php_hashcontext_object *hash, zend_long *magic, zval *zv); -typedef int (*php_hash_unserialize_func_t)(php_hashcontext_object *hash, zend_long magic, const zval *zv); +typedef hash_spec_result (*php_hash_serialize_func_t)(const php_hashcontext_object *hash, zend_long *magic, zval *zv); +typedef hash_spec_result (*php_hash_unserialize_func_t)(php_hashcontext_object *hash, zend_long magic, const zval *zv); typedef struct _php_hash_ops { const char *algo; @@ -148,10 +156,10 @@ extern PHP_HASH_API zend_class_entry *php_hashcontext_ce; PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(zend_string *algo); PHP_HASH_API void php_hash_register_algo(const char *algo, const php_hash_ops *ops); PHP_HASH_API zend_result php_hash_copy(const void *ops, const void *orig_context, void *dest_context); -PHP_HASH_API zend_result php_hash_serialize(const php_hashcontext_object *context, zend_long *magic, zval *zv); -PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *context, zend_long magic, const zval *zv); -PHP_HASH_API zend_result php_hash_serialize_spec(const php_hashcontext_object *context, zval *zv, const char *spec); -PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec); +PHP_HASH_API hash_spec_result php_hash_serialize(const php_hashcontext_object *context, zend_long *magic, zval *zv); +PHP_HASH_API hash_spec_result php_hash_unserialize(php_hashcontext_object *context, zend_long magic, const zval *zv); +PHP_HASH_API hash_spec_result php_hash_serialize_spec(const php_hashcontext_object *context, zval *zv, const char *spec); +PHP_HASH_API hash_spec_result php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec); static inline void *php_hash_alloc_context(const php_hash_ops *ops) { /* Zero out context memory so serialization doesn't expose internals */ diff --git a/ext/hash/tests/mhash_001.phpt b/ext/hash/tests/mhash_001.phpt index 29f0f473380b1..87da672550f65 100644 --- a/ext/hash/tests/mhash_001.phpt +++ b/ext/hash/tests/mhash_001.phpt @@ -35,77 +35,77 @@ foreach ($supported_hash_al as $hash=>$wanted) { } ?> --EXPECTF-- -Deprecated: Constant MHASH_MD5 is deprecated in %s on line %d +Deprecated: Constant MHASH_MD5 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_MD5 ok -Deprecated: Constant MHASH_SHA1 is deprecated in %s on line %d +Deprecated: Constant MHASH_SHA1 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_SHA1 ok -Deprecated: Constant MHASH_HAVAL256 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL256 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_HAVAL256 ok -Deprecated: Constant MHASH_HAVAL192 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL192 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_HAVAL192 ok -Deprecated: Constant MHASH_HAVAL224 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL224 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_HAVAL224 ok -Deprecated: Constant MHASH_HAVAL160 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL160 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_HAVAL160 ok -Deprecated: Constant MHASH_RIPEMD160 is deprecated in %s on line %d +Deprecated: Constant MHASH_RIPEMD160 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_RIPEMD160 ok -Deprecated: Constant MHASH_GOST is deprecated in %s on line %d +Deprecated: Constant MHASH_GOST is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_GOST ok -Deprecated: Constant MHASH_TIGER is deprecated in %s on line %d +Deprecated: Constant MHASH_TIGER is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_TIGER ok -Deprecated: Constant MHASH_CRC32 is deprecated in %s on line %d +Deprecated: Constant MHASH_CRC32 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_CRC32 ok -Deprecated: Constant MHASH_CRC32B is deprecated in %s on line %d +Deprecated: Constant MHASH_CRC32B is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d MHASH_CRC32B diff --git a/ext/hash/tests/mhash_003.phpt b/ext/hash/tests/mhash_003.phpt index f39e1ff387cb9..1a0983ee54f40 100644 --- a/ext/hash/tests/mhash_003.phpt +++ b/ext/hash/tests/mhash_003.phpt @@ -35,77 +35,77 @@ foreach ($supported_hash_al as $hash=>$wanted) { } ?> --EXPECTF-- -Deprecated: Constant MHASH_MD5 is deprecated in %s on line %d +Deprecated: Constant MHASH_MD5 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_MD5 ok -Deprecated: Constant MHASH_SHA1 is deprecated in %s on line %d +Deprecated: Constant MHASH_SHA1 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_SHA1 ok -Deprecated: Constant MHASH_HAVAL256 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL256 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_HAVAL256 ok -Deprecated: Constant MHASH_HAVAL224 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL224 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_HAVAL224 ok -Deprecated: Constant MHASH_HAVAL192 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL192 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_HAVAL192 ok -Deprecated: Constant MHASH_HAVAL160 is deprecated in %s on line %d +Deprecated: Constant MHASH_HAVAL160 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_HAVAL160 ok -Deprecated: Constant MHASH_RIPEMD160 is deprecated in %s on line %d +Deprecated: Constant MHASH_RIPEMD160 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_RIPEMD160 ok -Deprecated: Constant MHASH_GOST is deprecated in %s on line %d +Deprecated: Constant MHASH_GOST is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_GOST ok -Deprecated: Constant MHASH_TIGER is deprecated in %s on line %d +Deprecated: Constant MHASH_TIGER is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_TIGER ok -Deprecated: Constant MHASH_CRC32 is deprecated in %s on line %d +Deprecated: Constant MHASH_CRC32 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_CRC32 ok -Deprecated: Constant MHASH_CRC32B is deprecated in %s on line %d +Deprecated: Constant MHASH_CRC32B is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d Deprecated: Function mhash_keygen_s2k() is deprecated since 8.1 in %s on line %d MHASH_CRC32B diff --git a/ext/hash/tests/mhash_004.phpt b/ext/hash/tests/mhash_004.phpt index e47d48eb1a5d8..e7aa3c5e2df65 100644 --- a/ext/hash/tests/mhash_004.phpt +++ b/ext/hash/tests/mhash_004.phpt @@ -12,7 +12,7 @@ var_dump($algo); ?> --EXPECTF-- -Deprecated: Constant MHASH_MD5 is deprecated in %s on line %d +Deprecated: Constant MHASH_MD5 is deprecated since 8.5, as the mhash*() functions were deprecated in %s on line %d int(1) Deprecated: Function mhash() is deprecated since 8.1 in %s on line %d diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 157ee41a11a05..092e15669875e 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -2571,7 +2571,6 @@ static const php_stream_filter_ops php_iconv_stream_filter_ops = { /* {{{ php_iconv_stream_filter_create */ static php_stream_filter *php_iconv_stream_filter_factory_create(const char *name, zval *params, uint8_t persistent) { - php_stream_filter *retval = NULL; php_iconv_stream_filter *inst; const char *from_charset = NULL, *to_charset = NULL; size_t from_charset_len, to_charset_len; @@ -2602,12 +2601,7 @@ static php_stream_filter *php_iconv_stream_filter_factory_create(const char *nam return NULL; } - if (NULL == (retval = php_stream_filter_alloc(&php_iconv_stream_filter_ops, inst, persistent))) { - php_iconv_stream_filter_dtor(inst); - pefree(inst, persistent); - } - - return retval; + return php_stream_filter_alloc(&php_iconv_stream_filter_ops, inst, persistent); } /* }}} */ diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp index 6817f52ffb020..34176bf90e528 100644 --- a/ext/intl/breakiterator/breakiterator_iterators.cpp +++ b/ext/intl/breakiterator/breakiterator_iterators.cpp @@ -43,7 +43,7 @@ inline BreakIterator *_breakiter_prolog(zend_object_iterator *iter) if (bio->biter == NULL) { intl_errors_set(BREAKITER_ERROR_P(bio), U_INVALID_STATE_ERROR, "The BreakIterator object backing the PHP iterator is not " - "properly constructed", 0); + "properly constructed"); } return bio->biter; } diff --git a/ext/intl/breakiterator/breakiterator_methods.cpp b/ext/intl/breakiterator/breakiterator_methods.cpp index 56a3a35c97f81..c9791d4b23ae6 100644 --- a/ext/intl/breakiterator/breakiterator_methods.cpp +++ b/ext/intl/breakiterator/breakiterator_methods.cpp @@ -41,14 +41,13 @@ U_CFUNC PHP_METHOD(IntlBreakIterator, __construct) 0 ); } -static void _breakiter_factory(const char *func_name, - BreakIterator *(*func)(const Locale&, UErrorCode&), - INTERNAL_FUNCTION_PARAMETERS) +static void _breakiter_factory( + BreakIterator *(*func)(const Locale&, UErrorCode&), + INTERNAL_FUNCTION_PARAMETERS) { BreakIterator *biter; char *locale_str = NULL; size_t dummy; - char *msg; UErrorCode status = UErrorCode(); intl_error_reset(NULL); @@ -64,10 +63,7 @@ static void _breakiter_factory(const char *func_name, biter = func(Locale::createFromName(locale_str), status); intl_error_set_code(NULL, status); if (U_FAILURE(status)) { - spprintf(&msg, 0, "%s: error creating BreakIterator", - func_name); - intl_error_set_custom_msg(NULL, msg, 1); - efree(msg); + intl_error_set_custom_msg(NULL, "error creating BreakIterator"); RETURN_NULL(); } @@ -76,35 +72,35 @@ static void _breakiter_factory(const char *func_name, U_CFUNC PHP_METHOD(IntlBreakIterator, createWordInstance) { - _breakiter_factory("breakiter_create_word_instance", + _breakiter_factory( &BreakIterator::createWordInstance, INTERNAL_FUNCTION_PARAM_PASSTHRU); } U_CFUNC PHP_METHOD(IntlBreakIterator, createLineInstance) { - _breakiter_factory("breakiter_create_line_instance", + _breakiter_factory( &BreakIterator::createLineInstance, INTERNAL_FUNCTION_PARAM_PASSTHRU); } U_CFUNC PHP_METHOD(IntlBreakIterator, createCharacterInstance) { - _breakiter_factory("breakiter_create_character_instance", + _breakiter_factory( &BreakIterator::createCharacterInstance, INTERNAL_FUNCTION_PARAM_PASSTHRU); } U_CFUNC PHP_METHOD(IntlBreakIterator, createSentenceInstance) { - _breakiter_factory("breakiter_create_sentence_instance", + _breakiter_factory( &BreakIterator::createSentenceInstance, INTERNAL_FUNCTION_PARAM_PASSTHRU); } U_CFUNC PHP_METHOD(IntlBreakIterator, createTitleInstance) { - _breakiter_factory("breakiter_create_title_instance", + _breakiter_factory( &BreakIterator::createTitleInstance, INTERNAL_FUNCTION_PARAM_PASSTHRU); } @@ -149,12 +145,11 @@ U_CFUNC PHP_METHOD(IntlBreakIterator, setText) BREAKITER_METHOD_FETCH_OBJECT; ut = utext_openUTF8(ut, ZSTR_VAL(text), ZSTR_LEN(text), BREAKITER_ERROR_CODE_P(bio)); - INTL_METHOD_CHECK_STATUS(bio, "breakiter_set_text: error opening UText"); + INTL_METHOD_CHECK_STATUS(bio, "error opening UText"); bio->biter->setText(ut, BREAKITER_ERROR_CODE(bio)); utext_close(ut); /* ICU shallow clones the UText */ - INTL_METHOD_CHECK_STATUS(bio, "breakiter_set_text: error calling " - "BreakIterator::setText()"); + INTL_METHOD_CHECK_STATUS(bio, "error calling BreakIterator::setText()"); /* When ICU clones the UText, it does not copy the buffer, so we have to * keep the string buffer around by holding a reference to its zval. This @@ -302,10 +297,10 @@ U_CFUNC PHP_METHOD(IntlBreakIterator, getLocale) Z_PARAM_LONG(locale_type) ZEND_PARSE_PARAMETERS_END(); - /* Change to ValueError? */ + /* TODO: Change to ValueError? */ if (locale_type != ULOC_ACTUAL_LOCALE && locale_type != ULOC_VALID_LOCALE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "breakiter_get_locale: invalid locale type", 0); + "invalid locale type"); RETURN_FALSE; } @@ -313,8 +308,7 @@ U_CFUNC PHP_METHOD(IntlBreakIterator, getLocale) Locale locale = bio->biter->getLocale((ULocDataLocaleType)locale_type, BREAKITER_ERROR_CODE(bio)); - INTL_METHOD_CHECK_STATUS(bio, - "breakiter_get_locale: Call to ICU method has failed"); + INTL_METHOD_CHECK_STATUS(bio, "Call to ICU method has failed"); RETURN_STRING(locale.getName()); } diff --git a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp index c84972fe5b98c..a7c322b1d8169 100644 --- a/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp +++ b/ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp @@ -32,17 +32,16 @@ static inline RuleBasedBreakIterator *fetch_rbbi(BreakIterator_object *bio) { return (RuleBasedBreakIterator*)bio->biter; } -static void _php_intlrbbi_constructor_body(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) +U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, __construct) { - char *rules; - size_t rules_len; - bool compiled = false; - UErrorCode status = U_ZERO_ERROR; + zend_string *rules; + bool compiled = false; + UErrorCode status = U_ZERO_ERROR; BREAKITER_METHOD_INIT_VARS; object = ZEND_THIS; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(rules, rules_len) + Z_PARAM_STR(rules) Z_PARAM_OPTIONAL Z_PARAM_BOOL(compiled) ZEND_PARSE_PARAMETERS_END(); @@ -53,20 +52,14 @@ static void _php_intlrbbi_constructor_body(INTERNAL_FUNCTION_PARAMETERS, zend_er RETURN_THROWS(); } - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; - - // instantiation of ICU object RuleBasedBreakIterator *rbbi; if (!compiled) { UnicodeString rulesStr; UParseError parseError = UParseError(); - if (intl_stringFromChar(rulesStr, rules, rules_len, &status) - == FAILURE) { + if (intl_stringFromChar(rulesStr, ZSTR_VAL(rules), ZSTR_LEN(rules), &status) == FAILURE) { zend_throw_exception(IntlException_ce_ptr, - "IntlRuleBasedBreakIterator::__construct(): " - "rules were not a valid UTF-8 string", 0); + "IntlRuleBasedBreakIterator::__construct(): rules were not a valid UTF-8 string", 0); RETURN_THROWS(); } @@ -84,29 +77,16 @@ static void _php_intlrbbi_constructor_body(INTERNAL_FUNCTION_PARAMETERS, zend_er RETURN_THROWS(); } } else { // compiled - rbbi = new RuleBasedBreakIterator((uint8_t*)rules, rules_len, status); + rbbi = new RuleBasedBreakIterator(reinterpret_cast(ZSTR_VAL(rules)), ZSTR_LEN(rules), status); if (U_FAILURE(status)) { zend_throw_exception(IntlException_ce_ptr, - "IntlRuleBasedBreakIterator::__construct(): " - "unable to create instance from compiled rules", 0); + "IntlRuleBasedBreakIterator::__construct(): unable to create instance from compiled rules", 0); delete rbbi; RETURN_THROWS(); } } - breakiterator_object_create(return_value, rbbi, 0); -} - -U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, __construct) -{ - zend_error_handling error_handling; - bool error_handling_replaced = 0; - - return_value = ZEND_THIS; - _php_intlrbbi_constructor_body(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced); - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); - } + breakiterator_object_create(object, rbbi, false); } U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, getRules) @@ -125,8 +105,7 @@ U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, getRules) if (!u8str) { intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), - "rbbi_hash_code: Error converting result to UTF-8 string", - 0); + "Error converting result to UTF-8 string"); RETURN_FALSE; } RETVAL_STR(u8str); @@ -164,8 +143,7 @@ U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, getRuleStatusVec) BREAKITER_ERROR_CODE(bio)); if (U_FAILURE(BREAKITER_ERROR_CODE(bio))) { intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), - "rbbi_get_rule_status_vec: failed obtaining the status values", - 0); + "failed obtaining the status values"); RETURN_FALSE; } @@ -189,8 +167,7 @@ U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, getBinaryRules) if (rules_len > INT_MAX - 1) { intl_errors_set(BREAKITER_ERROR_P(bio), BREAKITER_ERROR_CODE(bio), - "rbbi_get_binary_rules: the rules are too large", - 0); + "the rules are too large"); RETURN_FALSE; } diff --git a/ext/intl/calendar/calendar.stub.php b/ext/intl/calendar/calendar.stub.php index 078ecb0c2daac..56602da0ec22f 100644 --- a/ext/intl/calendar/calendar.stub.php +++ b/ext/intl/calendar/calendar.stub.php @@ -90,11 +90,10 @@ class IntlCalendar private function __construct() {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type * @alias intlcal_create_instance */ - public static function createInstance($timezone = null, ?string $locale = null): ?IntlCalendar {} + public static function createInstance(IntlTimeZone|DateTimeZone|string|null $timezone = null, ?string $locale = null): ?IntlCalendar {} /** * @tentative-return-type @@ -355,11 +354,9 @@ public function setSkippedWallTimeOption(int $option): true {} public function setTime(float $timestamp): bool {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type - * @alias intlcal_set_time_zone */ - public function setTimeZone($timezone): bool {} + public function setTimeZone(IntlTimeZone|DateTimeZone|string|null $timezone): bool {} /** * @tentative-return-type diff --git a/ext/intl/calendar/calendar_arginfo.h b/ext/intl/calendar/calendar_arginfo.h index 9e050539b2e87..415113b613a2e 100644 --- a/ext/intl/calendar/calendar_arginfo.h +++ b/ext/intl/calendar/calendar_arginfo.h @@ -1,11 +1,11 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c014b88c9b6aa145ea20cc1f3fd719fe9f3d6966 */ + * Stub hash: 2fc12d1fde65efbec4305f4934a3f4b25282a552 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlCalendar___construct, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_IntlCalendar_createInstance, 0, 0, IntlCalendar, 1) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -165,7 +165,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlCalendar_set ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlCalendar_setTimeZone, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_IntlCalendar_toDateTime, 0, 0, DateTime, MAY_BE_FALSE) @@ -249,7 +249,7 @@ ZEND_FUNCTION(intlcal_set_lenient); ZEND_FUNCTION(intlcal_set_repeated_wall_time_option); ZEND_FUNCTION(intlcal_set_skipped_wall_time_option); ZEND_FUNCTION(intlcal_set_time); -ZEND_FUNCTION(intlcal_set_time_zone); +ZEND_METHOD(IntlCalendar, setTimeZone); ZEND_FUNCTION(intlcal_to_date_time); ZEND_METHOD(IntlGregorianCalendar, createFromDate); ZEND_METHOD(IntlGregorianCalendar, createFromDateTime); @@ -305,7 +305,7 @@ static const zend_function_entry class_IntlCalendar_methods[] = { ZEND_RAW_FENTRY("setRepeatedWallTimeOption", zif_intlcal_set_repeated_wall_time_option, arginfo_class_IntlCalendar_setRepeatedWallTimeOption, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("setSkippedWallTimeOption", zif_intlcal_set_skipped_wall_time_option, arginfo_class_IntlCalendar_setSkippedWallTimeOption, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("setTime", zif_intlcal_set_time, arginfo_class_IntlCalendar_setTime, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_RAW_FENTRY("setTimeZone", zif_intlcal_set_time_zone, arginfo_class_IntlCalendar_setTimeZone, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_ME(IntlCalendar, setTimeZone, arginfo_class_IntlCalendar_setTimeZone, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("toDateTime", zif_intlcal_to_date_time, arginfo_class_IntlCalendar_toDateTime, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_FE_END }; diff --git a/ext/intl/calendar/calendar_class.cpp b/ext/intl/calendar/calendar_class.cpp index f0582c64d2b2d..326b5475b73ab 100644 --- a/ext/intl/calendar/calendar_class.cpp +++ b/ext/intl/calendar/calendar_class.cpp @@ -71,7 +71,7 @@ U_CFUNC void calendar_object_construct(zval *object, CALENDAR_METHOD_FETCH_OBJECT_NO_CHECK; //populate to from object assert(co->ucal == NULL); - co->ucal = (Calendar*)calendar; + co->ucal = calendar; } /* {{{ clone handler for Calendar */ diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp index 9b7a37c0df523..c404286fe0944 100644 --- a/ext/intl/calendar/calendar_methods.cpp +++ b/ext/intl/calendar/calendar_methods.cpp @@ -72,22 +72,21 @@ U_CFUNC PHP_METHOD(IntlCalendar, __construct) U_CFUNC PHP_FUNCTION(intlcal_create_instance) { - zval *zv_timezone = NULL; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; char *locale_str = NULL; size_t locale_len = 0; - TimeZone *timeZone; UErrorCode status = U_ZERO_ERROR; intl_error_reset(NULL); ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(zv_timezone) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) Z_PARAM_STRING_OR_NULL(locale_str, locale_len) ZEND_PARSE_PARAMETERS_END(); - timeZone = timezone_process_timezone_argument(zv_timezone, NULL, - "intlcal_create_instance"); - if (timeZone == NULL) { + TimeZone *timeZone = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr); + if (timeZone == nullptr) { RETURN_NULL(); } @@ -99,7 +98,7 @@ U_CFUNC PHP_FUNCTION(intlcal_create_instance) Locale::createFromName(locale_str), status); if (UNEXPECTED(cal == NULL)) { delete timeZone; - intl_error_set(NULL, status, "Error creating ICU Calendar object", 0); + intl_error_set(NULL, status, "Error creating ICU Calendar object"); RETURN_NULL(); } @@ -179,8 +178,8 @@ U_CFUNC PHP_FUNCTION(intlcal_get_keyword_values_for_locale) Locale::createFromName(locale), (UBool)commonly_used, status); if (se == NULL) { - intl_error_set(NULL, status, "intlcal_get_keyword_values_for_locale: " - "error calling underlying method", 0); + intl_error_set(NULL, status, + "error calling underlying method"); RETURN_FALSE; } @@ -252,8 +251,7 @@ U_CFUNC PHP_FUNCTION(intlcal_get_time) CALENDAR_METHOD_FETCH_OBJECT; UDate result = co->ucal->getTime(CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, - "intlcal_get_time: error calling ICU Calendar::getTime"); + INTL_METHOD_CHECK_STATUS(co, "error calling ICU Calendar::getTime"); RETURN_DOUBLE((double)result); } @@ -293,31 +291,33 @@ U_CFUNC PHP_FUNCTION(intlcal_add) CALENDAR_METHOD_FETCH_OBJECT; co->ucal->add((UCalendarDateFields)field, (int32_t)amount, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlcal_add: Call to underlying method failed"); + INTL_METHOD_CHECK_STATUS(co, "Call to underlying method failed"); RETURN_TRUE; } +/* {{{ Set formatter's timezone. */ U_CFUNC PHP_FUNCTION(intlcal_set_time_zone) { - zval *zv_timezone; - TimeZone *timeZone; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; + CALENDAR_METHOD_INIT_VARS; - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), - "Oz!", &object, Calendar_ce_ptr, &zv_timezone) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJECT_OF_CLASS(object, Calendar_ce_ptr) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); CALENDAR_METHOD_FETCH_OBJECT; - if (zv_timezone == NULL) { + if (timezone_object == nullptr && timezone_string == nullptr) { RETURN_TRUE; /* the method does nothing if passed null */ } - timeZone = timezone_process_timezone_argument(zv_timezone, - CALENDAR_ERROR_P(co), "intlcal_set_time_zone"); - if (timeZone == NULL) { + TimeZone *timeZone = timezone_process_timezone_argument( + timezone_object, timezone_string, CALENDAR_ERROR_P(co)); + if (timeZone == nullptr) { RETURN_FALSE; } @@ -326,6 +326,34 @@ U_CFUNC PHP_FUNCTION(intlcal_set_time_zone) RETURN_TRUE; } +U_CFUNC PHP_METHOD(IntlCalendar, setTimeZone) +{ + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; + + CALENDAR_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); + + object = ZEND_THIS; + CALENDAR_METHOD_FETCH_OBJECT; + + if (timezone_object == nullptr && timezone_string == nullptr) { + RETURN_TRUE; /* the method does nothing if passed null */ + } + + TimeZone *timeZone = timezone_process_timezone_argument( + timezone_object, timezone_string, CALENDAR_ERROR_P(co)); + if (timeZone == nullptr) { + RETURN_FALSE; + } + + co->ucal->adoptTimeZone(timeZone); + + RETURN_TRUE; +} static void _php_intlcal_before_after( UBool (Calendar::*func)(const Calendar&, UErrorCode&) const, @@ -350,7 +378,7 @@ static void _php_intlcal_before_after( } UBool res = (co->ucal->*func)(*when_co->ucal, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlcal_before/after: Error calling ICU method"); + INTL_METHOD_CHECK_STATUS(co, "Error calling ICU method"); RETURN_BOOL((int)res); } @@ -490,7 +518,7 @@ U_CFUNC PHP_FUNCTION(intlcal_roll) co->ucal->roll((UCalendarDateFields)field, (int32_t)value, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlcal_roll: Error calling ICU Calendar::roll"); + INTL_METHOD_CHECK_STATUS(co, "Error calling ICU Calendar::roll"); RETURN_TRUE; } @@ -536,8 +564,7 @@ U_CFUNC PHP_FUNCTION(intlcal_field_difference) int32_t result = co->ucal->fieldDifference((UDate)when, (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, - "intlcal_field_difference: Call to ICU method has failed"); + INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed"); RETURN_LONG((zend_long)result); } @@ -570,8 +597,7 @@ U_CFUNC PHP_FUNCTION(intlcal_get_day_of_week_type) int32_t result = co->ucal->getDayOfWeekType( (UCalendarDaysOfWeek)dow, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, - "intlcal_get_day_of_week_type: Call to ICU method has failed"); + INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed"); RETURN_LONG((zend_long)result); } @@ -588,8 +614,7 @@ U_CFUNC PHP_FUNCTION(intlcal_get_first_day_of_week) CALENDAR_METHOD_FETCH_OBJECT; int32_t result = co->ucal->getFirstDayOfWeek(CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, - "intlcal_get_first_day_of_week: Call to ICU method has failed"); + INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed"); RETURN_LONG((zend_long)result); } @@ -647,8 +672,7 @@ U_CFUNC PHP_FUNCTION(intlcal_get_locale) Locale locale = co->ucal->getLocale((ULocDataLocaleType)locale_type, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, - "intlcal_get_locale: Call to ICU method has failed"); + INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed"); RETURN_STRING(locale.getName()); } @@ -671,8 +695,8 @@ U_CFUNC PHP_FUNCTION(intlcal_get_minimal_days_in_first_week) CALENDAR_METHOD_FETCH_OBJECT; uint8_t result = co->ucal->getMinimalDaysInFirstWeek(); - INTL_METHOD_CHECK_STATUS(co, - "intlcal_get_first_day_of_week: Call to ICU method has failed"); /* TODO Is it really a failure? */ + /* TODO Is it really a failure? */ + INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed"); RETURN_LONG((zend_long)result); } @@ -697,7 +721,7 @@ U_CFUNC PHP_FUNCTION(intlcal_get_time_zone) TimeZone *tz = co->ucal->getTimeZone().clone(); if (UNEXPECTED(tz == NULL)) { intl_errors_set(CALENDAR_ERROR_P(co), U_MEMORY_ALLOCATION_ERROR, - "intlcal_get_time_zone: could not clone TimeZone", 0); + "could not clone TimeZone"); RETURN_FALSE; } @@ -734,8 +758,7 @@ U_CFUNC PHP_FUNCTION(intlcal_get_weekend_transition) int32_t res = co->ucal->getWeekendTransition((UCalendarDaysOfWeek)dow, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlcal_get_weekend_transition: " - "Error calling ICU method"); + INTL_METHOD_CHECK_STATUS(co, "Error calling ICU method"); RETURN_LONG((zend_long)res); } @@ -752,8 +775,7 @@ U_CFUNC PHP_FUNCTION(intlcal_in_daylight_time) CALENDAR_METHOD_FETCH_OBJECT; UBool ret = co->ucal->inDaylightTime(CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlcal_in_daylight_time: " - "Error calling ICU method"); + INTL_METHOD_CHECK_STATUS(co, "Error calling ICU method"); RETURN_BOOL((int)ret); } @@ -829,8 +851,7 @@ U_CFUNC PHP_FUNCTION(intlcal_is_weekend) RETURN_BOOL((int)co->ucal->isWeekend()); } else { UBool ret = co->ucal->isWeekend((UDate)date, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlcal_is_weekend: " - "Error calling ICU method"); + INTL_METHOD_CHECK_STATUS(co, "Error calling ICU method"); RETURN_BOOL((int)ret); } } @@ -915,7 +936,7 @@ U_CFUNC PHP_FUNCTION(intlcal_equals) } UBool result = co->ucal->equals(*other_co->ucal, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlcal_equals: error calling ICU Calendar::equals"); + INTL_METHOD_CHECK_STATUS(co, "error calling ICU Calendar::equals"); RETURN_BOOL((int)result); } @@ -1028,16 +1049,14 @@ U_CFUNC PHP_FUNCTION(intlcal_from_date_time) datetime = php_date_obj_from_obj(date_obj); if (!datetime->time) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "intlcal_from_date_time: DateTime object is unconstructed", - 0); + "DateTime object is unconstructed"); goto error; } zend_call_method_with_0_params(date_obj, php_date_get_date_ce(), NULL, "gettimestamp", &zv_timestamp); if (Z_TYPE(zv_timestamp) != IS_LONG) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "intlcal_from_date_time: bad DateTime; call to " - "DateTime::getTimestamp() failed", 0); + "bad DateTime; call to DateTime::getTimestamp() failed"); zval_ptr_dtor(&zv_timestamp); goto error; } @@ -1046,7 +1065,7 @@ U_CFUNC PHP_FUNCTION(intlcal_from_date_time) timeZone = TimeZone::getGMT()->clone(); } else { timeZone = timezone_convert_datetimezone(datetime->time->zone_type, - datetime, 1, NULL, "intlcal_from_date_time"); + datetime, 1, NULL); if (timeZone == NULL) { goto error; } @@ -1060,16 +1079,16 @@ U_CFUNC PHP_FUNCTION(intlcal_from_date_time) Locale::createFromName(locale_str), status); if (UNEXPECTED(cal == NULL)) { delete timeZone; - intl_error_set(NULL, status, "intlcal_from_date_time: " - "error creating ICU Calendar object", 0); + intl_error_set(NULL, status, + "error creating ICU Calendar object"); goto error; } cal->setTime(((UDate)Z_LVAL(zv_timestamp)) * 1000., status); if (U_FAILURE(status)) { /* time zone was adopted by cal; should not be deleted here */ delete cal; - intl_error_set(NULL, status, "intlcal_from_date_time: " - "error creating ICU Calendar::setTime()", 0); + intl_error_set(NULL, status, + "error creating ICU Calendar::setTime()"); goto error; } @@ -1105,8 +1124,7 @@ U_CFUNC PHP_FUNCTION(intlcal_to_date_time) if (UNEXPECTED(date > (double)U_INT64_MAX || date < (double)U_INT64_MIN)) { intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR, - "intlcal_to_date_time: The calendar date is out of the " - "range for a 64-bit integer", 0); + "The calendar date is out of the range for a 64-bit integer"); RETURN_FALSE; } @@ -1119,7 +1137,7 @@ U_CFUNC PHP_FUNCTION(intlcal_to_date_time) /* Now get the time zone */ const TimeZone& tz = co->ucal->getTimeZone(); zval *timezone_zval = timezone_convert_to_datetimezone( - &tz, CALENDAR_ERROR_P(co), "intlcal_to_date_time", &tmp); + &tz, CALENDAR_ERROR_P(co), &tmp); if (timezone_zval == NULL) { zval_ptr_dtor(&ts_zval); RETURN_FALSE; @@ -1146,8 +1164,7 @@ U_CFUNC PHP_FUNCTION(intlcal_to_date_time) &retval, timezone_zval); if (Z_ISUNDEF(retval) || Z_TYPE(retval) == IS_FALSE) { intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR, - "intlcal_to_date_time: call to DateTime::setTimeZone has failed", - 1); + "call to DateTime::setTimeZone has failed"); zval_ptr_dtor(return_value); RETVAL_FALSE; goto error; diff --git a/ext/intl/calendar/gregoriancalendar_methods.cpp b/ext/intl/calendar/gregoriancalendar_methods.cpp index d6b8f0602dd09..0cc3a94d4c568 100644 --- a/ext/intl/calendar/gregoriancalendar_methods.cpp +++ b/ext/intl/calendar/gregoriancalendar_methods.cpp @@ -17,6 +17,7 @@ #endif #include "../intl_cppshims.h" +#include #include #include @@ -46,16 +47,14 @@ using icu::StringPiece; } static inline GregorianCalendar *fetch_greg(Calendar_object *co) { - return (GregorianCalendar*)co->ucal; + return static_cast(co->ucal); } static bool set_gregorian_calendar_time_zone(GregorianCalendar *gcal, UErrorCode status) { if (U_FAILURE(status)) { intl_error_set(NULL, status, - "IntlGregorianCalendar: Error creating ICU GregorianCalendar from date", - 0 - ); + "Error creating ICU GregorianCalendar from date"); return false; } @@ -64,10 +63,8 @@ static bool set_gregorian_calendar_time_zone(GregorianCalendar *gcal, UErrorCode UnicodeString tzstr = UnicodeString::fromUTF8(StringPiece(tzinfo->name)); if (tzstr.isBogus()) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "IntlGregorianCalendar: Could not create UTF-8 string " - "from PHP's default timezone name (see date_default_timezone_get())", - 0 - ); + "Could not create UTF-8 string from PHP's default timezone " + "name (see date_default_timezone_get())"); return false; } @@ -78,10 +75,10 @@ static bool set_gregorian_calendar_time_zone(GregorianCalendar *gcal, UErrorCode return true; } -static void _php_intlgregcal_constructor_body( - INTERNAL_FUNCTION_PARAMETERS, bool is_constructor, zend_error_handling *error_handling, bool *error_handling_replaced) +static void _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) { - zval *tz_object = NULL; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; zval args_a[6], *args = &args_a[0]; char *locale = NULL; @@ -116,25 +113,28 @@ static void _php_intlgregcal_constructor_body( // argument parsing if (variant <= 2) { - if (zend_parse_parameters(MIN(ZEND_NUM_ARGS(), 2), - "|z!s!", &tz_object, &locale, &locale_len) == FAILURE) { - RETURN_THROWS(); - } - } - if (variant > 2 && zend_parse_parameters(ZEND_NUM_ARGS(), - "lll|lll", &largs[0], &largs[1], &largs[2], &largs[3], &largs[4], - &largs[5]) == FAILURE) { - RETURN_THROWS(); + /* These dummy variables are needed because the 2 param constructor allows trailing nulls... */ + zval *dummy1, *dummy2, *dummy3, *dummy4; + ZEND_PARSE_PARAMETERS_START(0, 6) + Z_PARAM_OPTIONAL + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + Z_PARAM_STRING_OR_NULL(locale, locale_len) + Z_PARAM_ZVAL(dummy1) + Z_PARAM_ZVAL(dummy2) + Z_PARAM_ZVAL(dummy3) + Z_PARAM_ZVAL(dummy4) + ZEND_PARSE_PARAMETERS_END(); } - - if (error_handling != NULL) { - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; + if (variant > 2 + && zend_parse_parameters(ZEND_NUM_ARGS(), "lll|lll", + &largs[0], &largs[1], &largs[2], &largs[3], &largs[4], &largs[5]) == FAILURE + ) { + RETURN_THROWS(); } // instantion of ICU object Calendar_object *co = Z_INTL_CALENDAR_P(return_value); - GregorianCalendar *gcal = NULL; + std::unique_ptr gcal; if (co->ucal) { zend_throw_error(NULL, "IntlGregorianCalendar object is already constructed"); @@ -143,9 +143,9 @@ static void _php_intlgregcal_constructor_body( if (variant <= 2) { // From timezone and locale (0 to 2 arguments) - TimeZone *tz = timezone_process_timezone_argument(tz_object, NULL, - "intlgregcal_create_instance"); - if (tz == NULL) { + TimeZone *tz = timezone_process_timezone_argument(timezone_object, timezone_string, nullptr); + if (tz == nullptr) { + // TODO: Exception should always occur already? if (!EG(exception)) { zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); } @@ -159,15 +159,12 @@ static void _php_intlgregcal_constructor_body( locale = const_cast(intl_locale_get_default()); } - gcal = new GregorianCalendar(tz, Locale::createFromName(locale), - status); + gcal = std::unique_ptr(new GregorianCalendar(tz, Locale::createFromName(locale), + status)); // Should this throw? if (U_FAILURE(status)) { - intl_error_set(NULL, status, "intlgregcal_create_instance: error " - "creating ICU GregorianCalendar from time zone and locale", 0); - if (gcal) { - delete gcal; - } + intl_error_set(NULL, status, "error creating ICU " + "GregorianCalendar from time zone and locale"); delete tz; if (!is_constructor) { zval_ptr_dtor(return_value); @@ -177,26 +174,28 @@ static void _php_intlgregcal_constructor_body( } } else { // From date/time (3, 5 or 6 arguments) + GregorianCalendar *tmp; for (int i = 0; i < variant; i++) { ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE(largs[i], hasThis() ? (i-1) : i); } if (variant == 3) { - gcal = new GregorianCalendar((int32_t)largs[0], (int32_t)largs[1], + tmp = new GregorianCalendar((int32_t)largs[0], (int32_t)largs[1], (int32_t)largs[2], status); } else if (variant == 5) { - gcal = new GregorianCalendar((int32_t)largs[0], (int32_t)largs[1], + tmp = new GregorianCalendar((int32_t)largs[0], (int32_t)largs[1], (int32_t)largs[2], (int32_t)largs[3], (int32_t)largs[4], status); } else if (variant == 6) { - gcal = new GregorianCalendar((int32_t)largs[0], (int32_t)largs[1], + tmp = new GregorianCalendar((int32_t)largs[0], (int32_t)largs[1], (int32_t)largs[2], (int32_t)largs[3], (int32_t)largs[4], (int32_t)largs[5], status); } else { ZEND_UNREACHABLE(); } - if (!set_gregorian_calendar_time_zone(gcal, status)) { - delete gcal; + gcal = std::unique_ptr(tmp); + + if (!set_gregorian_calendar_time_zone(gcal.get(), status)) { if (!is_constructor) { zval_ptr_dtor(return_value); RETVAL_NULL(); @@ -205,36 +204,34 @@ static void _php_intlgregcal_constructor_body( } } - co->ucal = gcal; + co->ucal = gcal.release(); } U_CFUNC PHP_FUNCTION(intlgregcal_create_instance) { - intl_error_reset(NULL); - object_init_ex(return_value, GregorianCalendar_ce_ptr); - _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAM_PASSTHRU, /* is_constructor */ 0, NULL, NULL); + _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAM_PASSTHRU, /* is_constructor */ false); } U_CFUNC PHP_METHOD(IntlGregorianCalendar, __construct) { - zend_error_handling error_handling; - bool error_handling_replaced = 0; + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; return_value = ZEND_THIS; - _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAM_PASSTHRU, /* is_constructor */ 1, &error_handling, &error_handling_replaced); - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); - } + _php_intlgregcal_constructor_body(INTERNAL_FUNCTION_PARAM_PASSTHRU, /* is_constructor */ true); + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } U_CFUNC PHP_METHOD(IntlGregorianCalendar, createFromDate) { zend_long year, month, day; UErrorCode status = U_ZERO_ERROR; - zend_error_handling error_handling; Calendar_object *co; - GregorianCalendar *gcal; + std::unique_ptr gcal; intl_error_reset(NULL); @@ -248,20 +245,22 @@ U_CFUNC PHP_METHOD(IntlGregorianCalendar, createFromDate) ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE(month, 2); ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE(day, 3); - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, &error_handling); + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); - gcal = new GregorianCalendar((int32_t) year, (int32_t) month, (int32_t) day, status); - if (!set_gregorian_calendar_time_zone(gcal, status)) { - delete gcal; + gcal = std::unique_ptr(new GregorianCalendar((int32_t) year, (int32_t) month, (int32_t) day, status)); + if (!set_gregorian_calendar_time_zone(gcal.get(), status)) { + ZEND_ASSERT(EG(exception)); goto cleanup; } object_init_ex(return_value, GregorianCalendar_ce_ptr); co = Z_INTL_CALENDAR_P(return_value); - co->ucal = gcal; + co->ucal = gcal.release(); cleanup: - zend_restore_error_handling(&error_handling); + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } U_CFUNC PHP_METHOD(IntlGregorianCalendar, createFromDateTime) @@ -269,9 +268,8 @@ U_CFUNC PHP_METHOD(IntlGregorianCalendar, createFromDateTime) zend_long year, month, day, hour, minute, second; bool second_is_null = 1; UErrorCode status = U_ZERO_ERROR; - zend_error_handling error_handling; Calendar_object *co; - GregorianCalendar *gcal; + GregorianCalendar *tmp; intl_error_reset(NULL); @@ -291,25 +289,28 @@ U_CFUNC PHP_METHOD(IntlGregorianCalendar, createFromDateTime) ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE(hour, 4); ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE(minute, 5); - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, &error_handling); - if (second_is_null) { - gcal = new GregorianCalendar((int32_t) year, (int32_t) month, (int32_t) day, (int32_t) hour, (int32_t) minute, status); + tmp = new GregorianCalendar((int32_t) year, (int32_t) month, (int32_t) day, (int32_t) hour, (int32_t) minute, status); } else { ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE(second, 6); - gcal = new GregorianCalendar((int32_t) year, (int32_t) month, (int32_t) day, (int32_t) hour, (int32_t) minute, (int32_t) second, status); + tmp = new GregorianCalendar((int32_t) year, (int32_t) month, (int32_t) day, (int32_t) hour, (int32_t) minute, (int32_t) second, status); } - if (!set_gregorian_calendar_time_zone(gcal, status)) { - delete gcal; + auto gcal = std::unique_ptr(tmp); + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + if (!set_gregorian_calendar_time_zone(gcal.get(), status)) { + ZEND_ASSERT(EG(exception)); goto cleanup; } object_init_ex(return_value, GregorianCalendar_ce_ptr); co = Z_INTL_CALENDAR_P(return_value); - co->ucal = gcal; + // TODO: trying to get passed the ownership change step + co->ucal = gcal.release(); cleanup: - zend_restore_error_handling(&error_handling); + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } U_CFUNC PHP_FUNCTION(intlgregcal_set_gregorian_change) @@ -326,8 +327,7 @@ U_CFUNC PHP_FUNCTION(intlgregcal_set_gregorian_change) CALENDAR_METHOD_FETCH_OBJECT; fetch_greg(co)->setGregorianChange(date, CALENDAR_ERROR_CODE(co)); - INTL_METHOD_CHECK_STATUS(co, "intlgregcal_set_gregorian_change: error " - "calling ICU method"); + INTL_METHOD_CHECK_STATUS(co, "error calling ICU method"); RETURN_TRUE; } diff --git a/ext/intl/collator/collator_class.h b/ext/intl/collator/collator_class.h index 5c69c2e5affb2..311ab5623db4e 100644 --- a/ext/intl/collator/collator_class.h +++ b/ext/intl/collator/collator_class.h @@ -66,7 +66,7 @@ extern zend_class_entry *Collator_ce_ptr; intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); \ if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) \ { \ - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), msg, 0 ); \ + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), msg); \ RETURN_FALSE; \ } \ diff --git a/ext/intl/collator/collator_compare.c b/ext/intl/collator/collator_compare.c index f71d57f74f86a..bafaf166ac7a6 100644 --- a/ext/intl/collator/collator_compare.c +++ b/ext/intl/collator/collator_compare.c @@ -50,8 +50,7 @@ PHP_FUNCTION( collator_compare ) if (!co || !co->ucoll) { intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), - "Object not initialized", 0 ); + intl_errors_set_custom_msg(COLLATOR_ERROR_P( co ), "Object not initialized"); zend_throw_error(NULL, "Object not initialized"); RETURN_THROWS(); @@ -70,8 +69,7 @@ PHP_FUNCTION( collator_compare ) intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); /* Set error messages. */ - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), - "Error converting first argument to UTF-16", 0 ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Error converting first argument to UTF-16"); if (ustr1) { efree( ustr1 ); } @@ -86,8 +84,7 @@ PHP_FUNCTION( collator_compare ) intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); /* Set error messages. */ - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), - "Error converting second argument to UTF-16", 0 ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Error converting second argument to UTF-16"); if (ustr1) { efree( ustr1 ); } diff --git a/ext/intl/collator/collator_create.c b/ext/intl/collator/collator_create.c index 88dacc1c1db4e..5e6b0dee9ce6e 100644 --- a/ext/intl/collator/collator_create.c +++ b/ext/intl/collator/collator_create.c @@ -22,7 +22,7 @@ #include "intl_data.h" /* {{{ */ -static int collator_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) +static int collator_ctor(INTERNAL_FUNCTION_PARAMETERS) { char* locale; size_t locale_len = 0; @@ -35,11 +35,6 @@ static int collator_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *erro Z_PARAM_STRING(locale, locale_len) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); - if (error_handling != NULL) { - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; - } - INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); COLLATOR_METHOD_FETCH_OBJECT; @@ -49,7 +44,7 @@ static int collator_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *erro /* Open ICU collator. */ co->ucoll = ucol_open( locale, COLLATOR_ERROR_CODE_P( co ) ); - INTL_CTOR_CHECK_STATUS(co, "collator_create: unable to open ICU collator"); + INTL_CTOR_CHECK_STATUS(co, "unable to open ICU collator"); return SUCCESS; } /* }}} */ @@ -58,7 +53,7 @@ static int collator_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *erro PHP_FUNCTION( collator_create ) { object_init_ex( return_value, Collator_ce_ptr ); - if (collator_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { + if (collator_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { zval_ptr_dtor(return_value); RETURN_NULL(); } @@ -68,17 +63,16 @@ PHP_FUNCTION( collator_create ) /* {{{ Collator object constructor. */ PHP_METHOD( Collator, __construct ) { - zend_error_handling error_handling; - bool error_handling_replaced = 0; + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; return_value = ZEND_THIS; - if (collator_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) { - if (!EG(exception)) { - zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); - } - } - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); + if (collator_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + ZEND_ASSERT(EG(exception)); } + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } /* }}} */ diff --git a/ext/intl/collator/collator_locale.c b/ext/intl/collator/collator_locale.c index e1cdcdf2a6091..a7aafa74c26bd 100644 --- a/ext/intl/collator/collator_locale.c +++ b/ext/intl/collator/collator_locale.c @@ -43,8 +43,7 @@ PHP_FUNCTION( collator_get_locale ) if (!co || !co->ucoll) { intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), - "Object not initialized", 0 ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Object not initialized"); zend_throw_error(NULL, "Object not initialized"); RETURN_THROWS(); diff --git a/ext/intl/collator/collator_sort.c b/ext/intl/collator/collator_sort.c index 75466aacb07af..99b75aa0ef2be 100644 --- a/ext/intl/collator/collator_sort.c +++ b/ext/intl/collator/collator_sort.c @@ -24,10 +24,6 @@ #include "collator_convert.h" #include "intl_convert.h" -#if !defined(HAVE_PTRDIFF_T) && !defined(_PTRDIFF_T_DEFINED) -typedef zend_long ptrdiff_t; -#endif - /** * Declare 'index' which will point to sort key in sort key * buffer. @@ -363,8 +359,7 @@ PHP_FUNCTION( collator_sort_with_sort_keys ) if (!co || !co->ucoll) { intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), - "Object not initialized", 0 ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Object not initialized"); zend_throw_error(NULL, "Object not initialized"); RETURN_THROWS(); @@ -397,7 +392,7 @@ PHP_FUNCTION( collator_sort_with_sort_keys ) if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) ) { intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Sort with sort keys failed", 0 ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Sort with sort keys failed"); if( utf16_buf ) efree( utf16_buf ); @@ -520,8 +515,7 @@ PHP_FUNCTION( collator_get_sort_key ) if (!co || !co->ucoll) { intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), - "Object not initialized", 0 ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Object not initialized"); zend_throw_error(NULL, "Object not initialized"); RETURN_THROWS(); @@ -540,8 +534,7 @@ PHP_FUNCTION( collator_get_sort_key ) intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) ); /* Set error messages. */ - intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), - "Error converting first argument to UTF-16", 0 ); + intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Error converting first argument to UTF-16"); efree( ustr ); RETURN_FALSE; } @@ -557,6 +550,7 @@ PHP_FUNCTION( collator_get_sort_key ) key_len = ucol_getSortKey(co->ucoll, ustr, ustr_len, (uint8_t*)ZSTR_VAL(key_str), key_len); efree( ustr ); if(!key_len) { + zend_string_efree(key_str); RETURN_FALSE; } ZSTR_LEN(key_str) = key_len - 1; diff --git a/ext/intl/common/common.stub.php b/ext/intl/common/common.stub.php index c76ac9f756d4a..bbb8ad2179398 100644 --- a/ext/intl/common/common.stub.php +++ b/ext/intl/common/common.stub.php @@ -423,11 +423,10 @@ */ const U_MULTIPLE_DECIMAL_SEPARATORS = UNKNOWN; /** - * Typo: kept for backward compatibility. Use U_MULTIPLE_DECIMAL_SEPARATORS * @var int - * @deprecated * @cvalue U_MULTIPLE_DECIMAL_SEPERATORS */ +#[\Deprecated(since: '8.3', message: 'use U_MULTIPLE_DECIMAL_SEPARATORS instead')] const U_MULTIPLE_DECIMAL_SEPERATORS = UNKNOWN; /** * @var int diff --git a/ext/intl/common/common_arginfo.h b/ext/intl/common/common_arginfo.h index c5e023ecb8883..64b362a660a06 100644 --- a/ext/intl/common/common_arginfo.h +++ b/ext/intl/common/common_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 83971f2cec8c413d6207382e6ebc4ebf500e805f */ + * Stub hash: 9ed8bfc955a557c02171ec12b4634c60c6fb513e */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlIterator_current, 0, 0, IS_MIXED, 0) ZEND_END_ARG_INFO() @@ -113,7 +113,7 @@ static void register_common_symbols(int module_number) REGISTER_LONG_CONSTANT("U_UNEXPECTED_TOKEN", U_UNEXPECTED_TOKEN, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("U_FMT_PARSE_ERROR_START", U_FMT_PARSE_ERROR_START, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("U_MULTIPLE_DECIMAL_SEPARATORS", U_MULTIPLE_DECIMAL_SEPARATORS, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("U_MULTIPLE_DECIMAL_SEPERATORS", U_MULTIPLE_DECIMAL_SEPERATORS, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_U_MULTIPLE_DECIMAL_SEPERATORS = REGISTER_LONG_CONSTANT("U_MULTIPLE_DECIMAL_SEPERATORS", U_MULTIPLE_DECIMAL_SEPERATORS, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("U_MULTIPLE_EXPONENTIAL_SYMBOLS", U_MULTIPLE_EXPONENTIAL_SYMBOLS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("U_MALFORMED_EXPONENTIAL_PATTERN", U_MALFORMED_EXPONENTIAL_PATTERN, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("U_MULTIPLE_PERCENT_SYMBOLS", U_MULTIPLE_PERCENT_SYMBOLS, CONST_PERSISTENT); @@ -172,6 +172,14 @@ static void register_common_symbols(int module_number) REGISTER_LONG_CONSTANT("U_STRINGPREP_UNASSIGNED_ERROR", U_STRINGPREP_UNASSIGNED_ERROR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("U_STRINGPREP_CHECK_BIDI_ERROR", U_STRINGPREP_CHECK_BIDI_ERROR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("U_ERROR_LIMIT", U_ERROR_LIMIT, CONST_PERSISTENT); + + + zend_attribute *attribute_Deprecated_const_U_MULTIPLE_DECIMAL_SEPERATORS_0 = zend_add_global_constant_attribute(const_U_MULTIPLE_DECIMAL_SEPERATORS, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_U_MULTIPLE_DECIMAL_SEPERATORS_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); + attribute_Deprecated_const_U_MULTIPLE_DECIMAL_SEPERATORS_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_U_MULTIPLE_DECIMAL_SEPERATORS_0_arg1_str = zend_string_init("use U_MULTIPLE_DECIMAL_SEPARATORS instead", strlen("use U_MULTIPLE_DECIMAL_SEPARATORS instead"), 1); + ZVAL_STR(&attribute_Deprecated_const_U_MULTIPLE_DECIMAL_SEPERATORS_0->args[1].value, attribute_Deprecated_const_U_MULTIPLE_DECIMAL_SEPERATORS_0_arg1_str); + attribute_Deprecated_const_U_MULTIPLE_DECIMAL_SEPERATORS_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_IntlIterator(zend_class_entry *class_entry_Iterator) diff --git a/ext/intl/common/common_date.cpp b/ext/intl/common/common_date.cpp index e27a67ec55ad2..f2ca077554b49 100644 --- a/ext/intl/common/common_date.cpp +++ b/ext/intl/common/common_date.cpp @@ -30,11 +30,9 @@ using icu::UnicodeString; /* {{{ timezone_convert_datetimezone * The timezone in DateTime and DateTimeZone is not unified. */ -U_CFUNC TimeZone *timezone_convert_datetimezone(int type, - void *object, - int is_datetime, - intl_error *outside_error, - const char *func) +U_CFUNC TimeZone *timezone_convert_datetimezone( + int type, void *object, bool is_datetime, + intl_error *outside_error) { char *id = NULL, offset_id[] = "GMT+00:00"; @@ -58,11 +56,8 @@ U_CFUNC TimeZone *timezone_convert_datetimezone(int type, minutes *= minutes > 0 ? 1 : -1; if (offset_mins <= -24 * 60 || offset_mins >= 24 * 60) { - spprintf(&message, 0, "%s: object has an time zone offset " - "that's too large", func); intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); - efree(message); + "object has an time zone offset that's too large"); return NULL; } @@ -82,10 +77,9 @@ U_CFUNC TimeZone *timezone_convert_datetimezone(int type, UnicodeString s = UnicodeString(id, id_len, US_INV); timeZone = TimeZone::createTimeZone(s); if (*timeZone == TimeZone::getUnknown()) { - spprintf(&message, 0, "%s: time zone id '%s' " - "extracted from ext/date DateTimeZone not recognized", func, id); - intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); + spprintf(&message, 0, "time zone id '%s' " + "extracted from ext/date DateTimeZone not recognized", id); + intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR, message); efree(message); delete timeZone; return NULL; @@ -95,7 +89,7 @@ U_CFUNC TimeZone *timezone_convert_datetimezone(int type, /* }}} */ U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, TimeZone **tz, - intl_error *err, const char *func) + intl_error *err) { char *message; php_date_obj *datetime = php_date_obj_from_obj(obj); @@ -125,8 +119,8 @@ U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, Ti // TODO: Remove this when DateTimeInterface::getTimestamp() no longer has a tentative return type if (Z_TYPE(retval) != IS_LONG) { zval_ptr_dtor(&retval); - spprintf(&message, 0, "%s: %s::getTimestamp() did not return an int", func, ZSTR_VAL(obj->ce->name)); - intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR, message, 1); + spprintf(&message, 0, "%s::getTimestamp() did not return an int", ZSTR_VAL(obj->ce->name)); + intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR, message); efree(message); return FAILURE; } @@ -136,10 +130,9 @@ U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, Ti if (tz) { if (!datetime->time) { - spprintf(&message, 0, "%s: the %s object is not properly " - "initialized", func, ZSTR_VAL(obj->ce->name)); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); + spprintf(&message, 0, "the %s object is not properly " + "initialized", ZSTR_VAL(obj->ce->name)); + intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message); efree(message); return FAILURE; } @@ -147,13 +140,10 @@ U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, Ti *tz = TimeZone::getGMT()->clone(); } else { *tz = timezone_convert_datetimezone(datetime->time->zone_type, - datetime, 1, NULL, func); + datetime, 1, NULL); if (*tz == NULL) { - spprintf(&message, 0, "%s: could not convert DateTime's " - "time zone", func); intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); - efree(message); + "could not convert DateTime's time zone"); return FAILURE; } } @@ -162,12 +152,11 @@ U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, Ti return SUCCESS; } -U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func) +U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err) { double rv = ZEND_NAN; zend_long lv; int type; - char *message; if (err && U_FAILURE(err->code)) { return ZEND_NAN; @@ -182,11 +171,12 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func) } else if (type == IS_LONG) { rv = U_MILLIS_PER_SECOND * (double)lv; } else { - spprintf(&message, 0, "%s: string '%s' is not numeric, " - "which would be required for it to be a valid date", func, + char *message; + spprintf(&message, 0, "string '%s' is not numeric, " + "which would be required for it to be a valid date", Z_STRVAL_P(z)); intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); + message); efree(message); } break; @@ -198,42 +188,32 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func) break; case IS_OBJECT: if (instanceof_function(Z_OBJCE_P(z), php_date_get_interface_ce())) { - intl_datetime_decompose(Z_OBJ_P(z), &rv, nullptr, err, func); + intl_datetime_decompose(Z_OBJ_P(z), &rv, nullptr, err); } else if (instanceof_function(Z_OBJCE_P(z), Calendar_ce_ptr)) { Calendar_object *co = Z_INTL_CALENDAR_P(z); if (co->ucal == NULL) { - spprintf(&message, 0, "%s: IntlCalendar object is not properly " - "constructed", func); intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); - efree(message); + "IntlCalendar object is not properly constructed"); } else { UErrorCode status = UErrorCode(); rv = (double)co->ucal->getTime(status); if (U_FAILURE(status)) { - spprintf(&message, 0, "%s: call to internal " - "Calendar::getTime() has failed", func); - intl_errors_set(err, status, message, 1); - efree(message); + intl_errors_set(err, status, "call to internal Calendar::getTime() has failed"); } } } else { /* TODO: try with cast(), get() to obtain a number */ - spprintf(&message, 0, "%s: invalid object type for date/time " - "(only IntlCalendar and DateTimeInterface permitted)", func); intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); - efree(message); + "invalid object type for date/time " + "(only IntlCalendar and DateTimeInterface permitted)"); } break; case IS_REFERENCE: z = Z_REFVAL_P(z); goto try_again; default: - spprintf(&message, 0, "%s: invalid PHP type for date", func); intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); - efree(message); + "invalid PHP type for date"); break; } diff --git a/ext/intl/common/common_date.h b/ext/intl/common/common_date.h index e9fac3a02bd57..ef007c8eee687 100644 --- a/ext/intl/common/common_date.h +++ b/ext/intl/common/common_date.h @@ -28,11 +28,11 @@ U_CDECL_END using icu::TimeZone; -U_CFUNC TimeZone *timezone_convert_datetimezone(int type, void *object, int is_datetime, intl_error *outside_error, const char *func); -U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, TimeZone **tz, intl_error *err, const char *func); +U_CFUNC TimeZone *timezone_convert_datetimezone(int type, void *object, bool is_datetime, intl_error *outside_error); +U_CFUNC zend_result intl_datetime_decompose(zend_object *obj, double *millis, TimeZone **tz, intl_error *err); #endif -U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func); +U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err); #endif /* COMMON_DATE_H */ diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp index 4585a60f077aa..8cf9796717f4e 100644 --- a/ext/intl/common/common_enum.cpp +++ b/ext/intl/common/common_enum.cpp @@ -21,6 +21,10 @@ // Fix build on Windows/old versions of ICU #include +extern "C" { +#include +} + #include "common_enum.h" #include "common_arginfo.h" @@ -74,8 +78,7 @@ static void string_enum_current_move_forward(zend_object_iterator *iter) intl_error_set_code(NULL, INTLITERATOR_ERROR_CODE(ii)); if (U_FAILURE(INTLITERATOR_ERROR_CODE(ii))) { - intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii), - "Error fetching next iteration element", 0); + intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii), "Error fetching next iteration element"); } else if (result) { ZVAL_STRINGL(&zoi_iter->current, result, result_length); } //else we've reached the end of the enum, nothing more is required @@ -105,8 +108,7 @@ static void string_enum_rewind(zend_object_iterator *iter) intl_error_set_code(NULL, INTLITERATOR_ERROR_CODE(ii)); if (U_FAILURE(INTLITERATOR_ERROR_CODE(ii))) { - intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii), - "Error resetting enumeration", 0); + intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii), "Error resetting enumeration"); } else { iter->funcs->move_forward(iter); } @@ -268,7 +270,7 @@ PHP_METHOD(IntlIterator, rewind) ii->iterator->funcs->rewind(ii->iterator); } else { intl_errors_set(INTLITERATOR_ERROR_P(ii), U_UNSUPPORTED_ERROR, - "IntlIterator::rewind: rewind not supported", 0); + "rewind not supported"); } } diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index 20adc3a4ce3a7..c4c3c9b1d4cea 100644 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -33,21 +33,9 @@ if test "$PHP_INTL" != "no"; then formatter/formatter_parse.c grapheme/grapheme_string.c grapheme/grapheme_util.c - idn/idn.c intl_convert.c intl_error.c - locale/locale_class.c - locale/locale_methods.c - locale/locale.c listformatter/listformatter_class.c - msgformat/msgformat_attr.c - msgformat/msgformat_class.c - msgformat/msgformat_data.c - msgformat/msgformat_format.c - msgformat/msgformat_parse.c - msgformat/msgformat.c - normalizer/normalizer_class.c - normalizer/normalizer_normalize.c php_intl.c resourcebundle/resourcebundle_class.c resourcebundle/resourcebundle_iterator.c @@ -57,7 +45,6 @@ if test "$PHP_INTL" != "no"; then spoofchecker/spoofchecker_main.c transliterator/transliterator_class.c transliterator/transliterator_methods.c - uchar/uchar.c ]), [$ext_shared],, [$INTL_COMMON_FLAGS], @@ -78,12 +65,25 @@ if test "$PHP_INTL" != "no"; then calendar/calendar_class.cpp \ calendar/calendar_methods.cpp \ calendar/gregoriancalendar_methods.cpp \ + msgformat/msgformat_attr.cpp \ + msgformat/msgformat_class.cpp \ + msgformat/msgformat_data.cpp \ + msgformat/msgformat_format.cpp \ + msgformat/msgformat_parse.cpp \ + msgformat/msgformat.cpp \ + normalizer/normalizer_class.cpp \ + normalizer/normalizer_normalize.cpp \ breakiterator/breakiterator_class.cpp \ breakiterator/breakiterator_iterators.cpp \ breakiterator/breakiterator_methods.cpp \ breakiterator/rulebasedbreakiterator_methods.cpp \ breakiterator/codepointiterator_internal.cpp \ - breakiterator/codepointiterator_methods.cpp" + breakiterator/codepointiterator_methods.cpp \ + idn/idn.cpp \ + locale/locale_class.cpp \ + locale/locale_methods.cpp \ + locale/locale.cpp \ + uchar/uchar.cpp" PHP_REQUIRE_CXX() diff --git a/ext/intl/config.w32 b/ext/intl/config.w32 index b8161865d2540..fb3f0212729dd 100644 --- a/ext/intl/config.w32 +++ b/ext/intl/config.w32 @@ -43,25 +43,25 @@ if (PHP_INTL != "no") { listformatter_class.c \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/locale", "\ - locale.c \ - locale_class.c \ - locale_methods.c \ + locale.cpp \ + locale_class.cpp \ + locale_methods.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/msgformat", "\ - msgformat.c \ - msgformat_attr.c \ - msgformat_class.c \ - msgformat_data.c \ - msgformat_format.c \ + msgformat.cpp \ + msgformat_attr.cpp \ + msgformat_class.cpp \ + msgformat_data.cpp \ + msgformat_format.cpp \ msgformat_helpers.cpp \ - msgformat_parse.c \ + msgformat_parse.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/grapheme", "\ grapheme_string.c grapheme_util.c \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/normalizer", "\ - normalizer_class.c \ - normalizer_normalize.c \ + normalizer_class.cpp \ + normalizer_normalize.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/dateformat", "\ dateformat.c \ @@ -78,10 +78,10 @@ if (PHP_INTL != "no") { datepatterngenerator_methods.cpp \ ", "intl"); ADD_SOURCES(configure_module_dirname + "/uchar", "\ - uchar.c", + uchar.cpp", "intl"); ADD_SOURCES(configure_module_dirname + "/idn", "\ - idn.c", + idn.cpp", "intl"); ADD_SOURCES(configure_module_dirname + "/resourcebundle", "\ resourcebundle.c \ diff --git a/ext/intl/converter/converter.c b/ext/intl/converter/converter.c index 3aa7a53aa485b..759db5e18873a 100644 --- a/ext/intl/converter/converter.c +++ b/ext/intl/converter/converter.c @@ -24,6 +24,7 @@ #include "../intl_error.h" #include "../intl_common.h" #include "converter_arginfo.h" +#include "php_intl.h" typedef struct _php_converter_object { UConverter *src, *dest; @@ -42,8 +43,8 @@ static zend_class_entry *php_converter_ce; static zend_object_handlers php_converter_object_handlers; #define CONV_GET(pzv) (Z_INTL_CONVERTER_P((pzv))) -#define THROW_UFAILURE(obj, fname, error) php_converter_throw_failure(obj, error, \ - fname "() returned error " ZEND_LONG_FMT ": %s", (zend_long)error, u_errorName(error)) +#define THROW_UFAILURE(obj, error) php_converter_throw_failure(obj, error, \ + "returned error " ZEND_LONG_FMT ": %s", (zend_long)error, u_errorName(error)) /* {{{ php_converter_throw_failure */ static inline void php_converter_throw_failure(php_converter_object *objval, UErrorCode error, const char *format, ...) { @@ -55,7 +56,7 @@ static inline void php_converter_throw_failure(php_converter_object *objval, UEr vsnprintf(message, sizeof(message), format, vargs); va_end(vargs); - intl_errors_set(err, error, message, 1); + intl_errors_set(err, error, message); } /* }}} */ @@ -90,7 +91,7 @@ static void php_converter_default_callback(zval *return_value, zval *zobj, zend_ */ ucnv_getSubstChars(objval->src, chars, &chars_len, &uerror); if (U_FAILURE(uerror)) { - THROW_UFAILURE(objval, "ucnv_getSubstChars", uerror); + THROW_UFAILURE(objval, uerror); chars[0] = 0x1A; chars[1] = 0; chars_len = 1; @@ -341,7 +342,7 @@ static inline bool php_converter_set_callbacks(php_converter_object *objval, UCo ucnv_setToUCallBack(cnv, (UConverterToUCallback)php_converter_to_u_callback, (const void*)objval, NULL, NULL, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_setToUCallBack", error); + THROW_UFAILURE(objval, error); ret = 0; } @@ -349,7 +350,7 @@ static inline bool php_converter_set_callbacks(php_converter_object *objval, UCo ucnv_setFromUCallBack(cnv, (UConverterFromUCallback)php_converter_from_u_callback, (const void*)objval, NULL, NULL, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_setFromUCallBack", error); + THROW_UFAILURE(objval, error); ret = 0; } return ret; @@ -370,14 +371,17 @@ static bool php_converter_set_encoding(php_converter_object *objval, /* Should never happen */ actual_encoding = "(unknown)"; } - php_error_docref(NULL, E_WARNING, "Ambiguous encoding specified, using %s", actual_encoding); + char *msg; + spprintf(&msg, 0, "Ambiguous encoding specified, using %s", actual_encoding); + intl_error_set(NULL, error, msg); + efree(msg); } else if (U_FAILURE(error)) { if (objval) { - THROW_UFAILURE(objval, "ucnv_open", error); + THROW_UFAILURE(objval, error); } else { char *msg; spprintf(&msg, 0, "Error setting encoding: %d - %s", (int)error, u_errorName(error)); - intl_error_set(NULL, error, msg, 1); + intl_error_set(NULL, error, msg); efree(msg); } return false; @@ -439,7 +443,7 @@ static void php_converter_do_get_encoding(php_converter_object *objval, UConvert name = ucnv_getName(cnv, &objval->error.code); if (U_FAILURE(objval->error.code)) { - THROW_UFAILURE(objval, "ucnv_getName()", objval->error.code); + THROW_UFAILURE(objval, objval->error.code); RETURN_FALSE; } @@ -474,7 +478,7 @@ static void php_converter_do_get_type(php_converter_object *objval, UConverter * t = ucnv_getType(cnv); if (U_FAILURE(objval->error.code)) { - THROW_UFAILURE(objval, "ucnv_getType", objval->error.code); + THROW_UFAILURE(objval, objval->error.code); RETURN_FALSE; } @@ -530,10 +534,23 @@ PHP_METHOD(UConverter, __construct) { Z_PARAM_STRING_OR_NULL(src, src_len) ZEND_PARSE_PARAMETERS_END(); - php_converter_set_encoding(objval, &(objval->src), src, src_len ); - php_converter_set_encoding(objval, &(objval->dest), dest, dest_len); + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; + if (UNEXPECTED(!php_converter_set_encoding(objval, &(objval->src), src, src_len))) { + ZEND_ASSERT(EG(exception)); + goto cleanup; + } + if (UNEXPECTED(!php_converter_set_encoding(objval, &(objval->dest), dest, dest_len))) { + ZEND_ASSERT(EG(exception)); + goto cleanup; + } php_converter_resolve_callback(&objval->to_cache, Z_OBJ_P(ZEND_THIS), ZEND_STRL("toUCallback")); php_converter_resolve_callback(&objval->from_cache, Z_OBJ_P(ZEND_THIS), ZEND_STRL("fromUCallback")); +cleanup: + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } /* }}} */ @@ -554,7 +571,7 @@ PHP_METHOD(UConverter, setSubstChars) { UErrorCode error = U_ZERO_ERROR; ucnv_setSubstChars(objval->src, chars, chars_len, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_setSubstChars", error); + THROW_UFAILURE(objval, error); ret = 0; } } else { @@ -566,7 +583,7 @@ PHP_METHOD(UConverter, setSubstChars) { UErrorCode error = U_ZERO_ERROR; ucnv_setSubstChars(objval->dest, chars, chars_len, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_setSubstChars", error); + THROW_UFAILURE(objval, error); ret = 0; } } else { @@ -597,7 +614,7 @@ PHP_METHOD(UConverter, getSubstChars) { */ ucnv_getSubstChars(objval->src, chars, &chars_len, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_getSubstChars", error); + THROW_UFAILURE(objval, error); RETURN_FALSE; } @@ -624,7 +641,7 @@ static zend_string* php_converter_do_convert(UConverter *dest_cnv, /* Get necessary buffer size first */ temp_len = 1 + ucnv_toUChars(src_cnv, NULL, 0, src, src_len, &error); if (U_FAILURE(error) && error != U_BUFFER_OVERFLOW_ERROR) { - THROW_UFAILURE(objval, "ucnv_toUChars", error); + THROW_UFAILURE(objval, error); return NULL; } temp = safe_emalloc(sizeof(UChar), temp_len, sizeof(UChar)); @@ -633,7 +650,7 @@ static zend_string* php_converter_do_convert(UConverter *dest_cnv, error = U_ZERO_ERROR; temp_len = ucnv_toUChars(src_cnv, temp, temp_len, src, src_len, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_toUChars", error); + THROW_UFAILURE(objval, error); efree(temp); return NULL; } @@ -642,7 +659,7 @@ static zend_string* php_converter_do_convert(UConverter *dest_cnv, /* Get necessary output buffer size */ ret_len = ucnv_fromUChars(dest_cnv, NULL, 0, temp, temp_len, &error); if (U_FAILURE(error) && error != U_BUFFER_OVERFLOW_ERROR) { - THROW_UFAILURE(objval, "ucnv_fromUChars", error); + THROW_UFAILURE(objval, error); efree(temp); return NULL; } @@ -654,7 +671,7 @@ static zend_string* php_converter_do_convert(UConverter *dest_cnv, ZSTR_LEN(ret) = ucnv_fromUChars(dest_cnv, ZSTR_VAL(ret), ret_len+1, temp, temp_len, &error); efree(temp); if (U_FAILURE(error)) { - THROW_UFAILURE(objval, "ucnv_fromUChars", error); + THROW_UFAILURE(objval, error); zend_string_efree(ret); return NULL; } @@ -758,7 +775,7 @@ PHP_METHOD(UConverter, transcode) { } if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "transcode", error); + THROW_UFAILURE(NULL, error); RETVAL_FALSE; } } else { @@ -831,7 +848,7 @@ PHP_METHOD(UConverter, getAliases) { count = ucnv_countAliases(name, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "ucnv_countAliases", error); + THROW_UFAILURE(NULL, error); RETURN_FALSE; } @@ -843,7 +860,7 @@ PHP_METHOD(UConverter, getAliases) { error = U_ZERO_ERROR; alias = ucnv_getAlias(name, i, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "ucnv_getAlias", error); + THROW_UFAILURE(NULL, error); zend_array_destroy(Z_ARR_P(return_value)); RETURN_NULL(); } @@ -866,7 +883,7 @@ PHP_METHOD(UConverter, getStandards) { UErrorCode error = U_ZERO_ERROR; const char *name = ucnv_getStandard(i, &error); if (U_FAILURE(error)) { - THROW_UFAILURE(NULL, "ucnv_getStandard", error); + THROW_UFAILURE(NULL, error); zend_array_destroy(Z_ARR_P(return_value)); RETURN_NULL(); } diff --git a/ext/intl/dateformat/dateformat.stub.php b/ext/intl/dateformat/dateformat.stub.php index 7582af2717fbe..89ebc5f61c0ec 100644 --- a/ext/intl/dateformat/dateformat.stub.php +++ b/ext/intl/dateformat/dateformat.stub.php @@ -32,20 +32,18 @@ class IntlDateFormatter public const int TRADITIONAL = UNKNOWN; /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @param IntlCalendar|int|null $calendar */ public function __construct( ?string $locale, int $dateType = IntlDateFormatter::FULL, int $timeType = IntlDateFormatter::FULL, - $timezone = null, + IntlTimeZone|DateTimeZone|string|null $timezone = null, $calendar = null, ?string $pattern = null ) {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type * @alias datefmt_create */ @@ -53,7 +51,7 @@ public static function create( ?string $locale, int $dateType = IntlDateFormatter::FULL, int $timeType = IntlDateFormatter::FULL, - $timezone = null, + IntlTimeZone|DateTimeZone|string|null $timezone = null, IntlCalendar|int|null $calendar = null, ?string $pattern = null ): ?IntlDateFormatter {} @@ -101,11 +99,9 @@ public function getCalendarObject(): IntlCalendar|false|null {} public function getTimeZone(): IntlTimeZone|false {} /** - * @param IntlTimeZone|DateTimeZone|string|null $timezone * @tentative-return-type - * @alias datefmt_set_timezone */ - public function setTimeZone($timezone): bool {} + public function setTimeZone(IntlTimeZone|DateTimeZone|string|null $timezone): bool {} /** * @tentative-return-type diff --git a/ext/intl/dateformat/dateformat_arginfo.h b/ext/intl/dateformat/dateformat_arginfo.h index b57cb79468f2b..d6d0306506f81 100644 --- a/ext/intl/dateformat/dateformat_arginfo.h +++ b/ext/intl/dateformat/dateformat_arginfo.h @@ -1,11 +1,11 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 56b66b1b51220ddbff698ec4c9a6ae60f3e0bfb0 */ + * Stub hash: 160d05ec65c45b66b13eaecbef20b3c59bfb33d1 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDateFormatter___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dateType, IS_LONG, 0, "IntlDateFormatter::FULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeType, IS_LONG, 0, "IntlDateFormatter::FULL") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, calendar, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -14,7 +14,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_IntlDateFormatter ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dateType, IS_LONG, 0, "IntlDateFormatter::FULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeType, IS_LONG, 0, "IntlDateFormatter::FULL") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_OBJ_TYPE_MASK(0, calendar, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -40,7 +40,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_IntlDateForm ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlDateFormatter_setTimeZone, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_IntlDateFormatter_setPattern, 0, 1, _IS_BOOL, 0) @@ -100,7 +100,7 @@ ZEND_FUNCTION(datefmt_set_calendar); ZEND_FUNCTION(datefmt_get_timezone_id); ZEND_FUNCTION(datefmt_get_calendar_object); ZEND_FUNCTION(datefmt_get_timezone); -ZEND_FUNCTION(datefmt_set_timezone); +ZEND_METHOD(IntlDateFormatter, setTimeZone); ZEND_FUNCTION(datefmt_set_pattern); ZEND_FUNCTION(datefmt_get_pattern); ZEND_FUNCTION(datefmt_get_locale); @@ -124,7 +124,7 @@ static const zend_function_entry class_IntlDateFormatter_methods[] = { ZEND_RAW_FENTRY("getTimeZoneId", zif_datefmt_get_timezone_id, arginfo_class_IntlDateFormatter_getTimeZoneId, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getCalendarObject", zif_datefmt_get_calendar_object, arginfo_class_IntlDateFormatter_getCalendarObject, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getTimeZone", zif_datefmt_get_timezone, arginfo_class_IntlDateFormatter_getTimeZone, ZEND_ACC_PUBLIC, NULL, NULL) - ZEND_RAW_FENTRY("setTimeZone", zif_datefmt_set_timezone, arginfo_class_IntlDateFormatter_setTimeZone, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_ME(IntlDateFormatter, setTimeZone, arginfo_class_IntlDateFormatter_setTimeZone, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("setPattern", zif_datefmt_set_pattern, arginfo_class_IntlDateFormatter_setPattern, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getPattern", zif_datefmt_get_pattern, arginfo_class_IntlDateFormatter_getPattern, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getLocale", zif_datefmt_get_locale, arginfo_class_IntlDateFormatter_getLocale, ZEND_ACC_PUBLIC, NULL, NULL) diff --git a/ext/intl/dateformat/dateformat_attrcpp.cpp b/ext/intl/dateformat/dateformat_attrcpp.cpp index 1fb5b514bc6a3..13dadc9c96973 100644 --- a/ext/intl/dateformat/dateformat_attrcpp.cpp +++ b/ext/intl/dateformat/dateformat_attrcpp.cpp @@ -71,8 +71,7 @@ U_CFUNC PHP_FUNCTION(datefmt_get_timezone) TimeZone *tz_clone = tz.clone(); if (UNEXPECTED(tz_clone == NULL)) { intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR, - "datefmt_get_timezone: Out of memory when cloning time zone", - 0); + "Out of memory when cloning time zone"); RETURN_FALSE; } @@ -82,21 +81,46 @@ U_CFUNC PHP_FUNCTION(datefmt_get_timezone) /* {{{ Set formatter's timezone. */ U_CFUNC PHP_FUNCTION(datefmt_set_timezone) { - zval *timezone_zv; - TimeZone *timezone; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; DATE_FORMAT_METHOD_INIT_VARS; - if ( zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), - "Oz", &object, IntlDateFormatter_ce_ptr, &timezone_zv) == FAILURE) { - RETURN_THROWS(); + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJECT_OF_CLASS(object, IntlDateFormatter_ce_ptr) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); + + DATE_FORMAT_METHOD_FETCH_OBJECT; + + TimeZone *timezone = timezone_process_timezone_argument( + timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo)); + if (timezone == nullptr) { + RETURN_FALSE; } + fetch_datefmt(dfo)->adoptTimeZone(timezone); + + RETURN_TRUE; +} + +U_CFUNC PHP_METHOD(IntlDateFormatter, setTimeZone) +{ + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; + + DATE_FORMAT_METHOD_INIT_VARS; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) + ZEND_PARSE_PARAMETERS_END(); + + object = ZEND_THIS; DATE_FORMAT_METHOD_FETCH_OBJECT; - timezone = timezone_process_timezone_argument(timezone_zv, - INTL_DATA_ERROR_P(dfo), "datefmt_set_timezone"); - if (timezone == NULL) { + TimeZone *timezone = timezone_process_timezone_argument( + timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo)); + if (timezone == nullptr) { RETURN_FALSE; } @@ -146,8 +170,7 @@ U_CFUNC PHP_FUNCTION(datefmt_get_calendar_object) Calendar *cal_clone = cal->clone(); if (UNEXPECTED(cal_clone == NULL)) { intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR, - "datefmt_get_calendar_object: Out of memory when cloning " - "calendar", 0); + "Out of memory when cloning calendar"); RETURN_FALSE; } @@ -187,7 +210,7 @@ U_CFUNC PHP_FUNCTION(datefmt_set_calendar) // must store the requested locale on object creation if (datefmt_process_calendar_arg(calendar_obj, calendar_long, calendar_is_null, locale, - "datefmt_set_calendar", INTL_DATA_ERROR_P(dfo), cal, cal_type, cal_owned) == FAILURE + INTL_DATA_ERROR_P(dfo), cal, cal_type, cal_owned) == FAILURE ) { RETURN_FALSE; } @@ -197,8 +220,7 @@ U_CFUNC PHP_FUNCTION(datefmt_set_calendar) TimeZone *old_timezone = fetch_datefmt(dfo)->getTimeZone().clone(); if (UNEXPECTED(old_timezone == NULL)) { intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR, - "datefmt_set_calendar: Out of memory when cloning calendar", - 0); + "Out of memory when cloning calendar"); delete cal; RETURN_FALSE; } @@ -207,8 +229,7 @@ U_CFUNC PHP_FUNCTION(datefmt_set_calendar) cal = cal->clone(); if (UNEXPECTED(cal == NULL)) { intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR, - "datefmt_set_calendar: Out of memory when cloning calendar", - 0); + "Out of memory when cloning calendar"); RETURN_FALSE; } } diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index d071c7d9d2ed7..251f6f3fbc9b0 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -22,6 +22,7 @@ extern "C" { #include #include +#include #include "php_intl.h" #include "dateformat_create.h" @@ -45,7 +46,7 @@ extern "C" { UDAT_PATTERN == (i)) /* {{{ */ -static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) +static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) { zval *object; char *locale_str; @@ -59,7 +60,8 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin Calendar *cal = NULL; zend_long calendar_type; bool calendar_owned; - zval *timezone_zv = NULL; + zend_object *timezone_object = nullptr; + zend_string *timezone_string = nullptr; TimeZone *timezone = NULL; bool explicit_tz; char* pattern_str = NULL; @@ -76,33 +78,28 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin Z_PARAM_OPTIONAL Z_PARAM_LONG(date_type) Z_PARAM_LONG(time_type) - Z_PARAM_ZVAL(timezone_zv) + Z_PARAM_OBJ_OR_STR_OR_NULL(timezone_object, timezone_string) Z_PARAM_OBJ_OF_CLASS_OR_LONG_OR_NULL(calendar_obj, Calendar_ce_ptr, calendar_long, calendar_is_null) Z_PARAM_STRING_OR_NULL(pattern_str, pattern_str_len) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); - if (error_handling != NULL) { - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; - } - DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; if (DATE_FORMAT_OBJECT(dfo) != NULL) { - intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: cannot call constructor twice", 0); + intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "cannot call constructor twice"); return FAILURE; } if (!INTL_UDATE_FMT_OK(date_type)) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid date format style", 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid date format style"); return FAILURE; } if (!INTL_UDATE_FMT_OK(time_type)) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid time format style", 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid time format style"); return FAILURE; } if (date_type == UDAT_PATTERN && time_type != UDAT_PATTERN) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: time format must be UDAT_PATTERN if date format is UDAT_PATTERN", 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "time format must be UDAT_PATTERN if date format is UDAT_PATTERN"); return FAILURE; } @@ -110,28 +107,32 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin if (locale_len == 0) { locale_str = (char *) intl_locale_get_default(); } - locale = Locale::createFromName(locale_str); + + char* canonicalized_locale = canonicalize_locale_string(locale_str); + const char* final_locale = canonicalized_locale ? canonicalized_locale : locale_str; + const char* stored_locale = canonicalized_locale ? canonicalized_locale : locale_str; + + locale = Locale::createFromName(final_locale); /* get*Name accessors being set does not preclude being bogus */ if (locale.isBogus() || ((locale_len == 1 && locale_str[0] != 'C') || (locale_len > 1 && strlen(locale.getISO3Language()) == 0))) { - zend_argument_value_error(1, "\"%s\" is invalid", locale_str); - return FAILURE; + zend_argument_value_error(1, "\"%s\" is invalid", locale_str); + goto error; } /* process calendar */ - if (datefmt_process_calendar_arg(calendar_obj, calendar_long, calendar_is_null, locale, "datefmt_create", + if (datefmt_process_calendar_arg(calendar_obj, calendar_long, calendar_is_null, locale, INTL_DATA_ERROR_P(dfo), cal, calendar_type, calendar_owned) == FAILURE ) { goto error; } /* process timezone */ - explicit_tz = timezone_zv != NULL && Z_TYPE_P(timezone_zv) != IS_NULL; + explicit_tz = timezone_object != nullptr || timezone_string != nullptr; if (explicit_tz || calendar_owned ) { //we have an explicit time zone or a non-object calendar - timezone = timezone_process_timezone_argument(timezone_zv, - INTL_DATA_ERROR_P(dfo), "datefmt_create"); - if (timezone == NULL) { + timezone = timezone_process_timezone_argument(timezone_object, timezone_string, INTL_DATA_ERROR_P(dfo)); + if (timezone == nullptr) { goto error; } } @@ -142,20 +143,20 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(dfo)); if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { /* object construction -> only set global error */ - intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: " - "error converting pattern to UTF-16", 0); + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), + "error converting pattern to UTF-16"); goto error; } } DATE_FORMAT_OBJECT(dfo) = udat_open((UDateFormatStyle)time_type, - (UDateFormatStyle)date_type, locale_str, NULL, 0, svalue, + (UDateFormatStyle)date_type, final_locale, NULL, 0, svalue, slength, &INTL_DATA_ERROR_CODE(dfo)); if (pattern_str && pattern_str_len > 0) { udat_applyPattern(DATE_FORMAT_OBJECT(dfo), true, svalue, slength); if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { - intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: error applying pattern", 0); + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "error applying pattern"); goto error; } } @@ -173,8 +174,7 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin df->adoptTimeZone(timezone); } } else { - intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: date " - "formatter creation failed", 0); + intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "date formatter creation failed"); goto error; } @@ -182,9 +182,13 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin dfo->date_type = date_type; dfo->time_type = time_type; dfo->calendar = calendar_type; - dfo->requested_locale = estrdup(locale_str); + /* Store the canonicalized locale, or fallback to original if canonicalization failed */ + dfo->requested_locale = estrdup(stored_locale); error: + if (canonicalized_locale) { + efree(canonicalized_locale); + } if (svalue) { efree(svalue); } @@ -203,7 +207,7 @@ static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handlin U_CFUNC PHP_FUNCTION( datefmt_create ) { object_init_ex( return_value, IntlDateFormatter_ce_ptr ); - if (datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { + if (datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { zval_ptr_dtor(return_value); RETURN_NULL(); } @@ -213,21 +217,18 @@ U_CFUNC PHP_FUNCTION( datefmt_create ) /* {{{ IntlDateFormatter object constructor. */ U_CFUNC PHP_METHOD( IntlDateFormatter, __construct ) { - zend_error_handling error_handling; - bool error_handling_replaced = 0; + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; /* return_value param is being changed, therefore we will always return * NULL here */ return_value = ZEND_THIS; - if (datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) { - if (!EG(exception)) { - zend_string *err = intl_error_get_message(NULL); - zend_throw_exception(IntlException_ce_ptr, ZSTR_VAL(err), intl_error_get_code(NULL)); - zend_string_release_ex(err, 0); - } - } - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); + if (datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + ZEND_ASSERT(EG(exception)); } + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } /* }}} */ diff --git a/ext/intl/dateformat/dateformat_format.c b/ext/intl/dateformat/dateformat_format.c index f4ef8a40d6458..ee3abd052d669 100644 --- a/ext/intl/dateformat/dateformat_format.c +++ b/ext/intl/dateformat/dateformat_format.c @@ -66,17 +66,17 @@ static int32_t internal_get_arr_ele(IntlDateFormatter_object *dfo, if ((ele_value = zend_hash_str_find_deref(hash_arr, key_name, strlen(key_name))) != NULL) { if(Z_TYPE_P(ele_value) != IS_LONG) { - spprintf(&message, 0, "datefmt_format: parameter array contains " + spprintf(&message, 0, "parameter array contains " "a non-integer element for key '%s'", key_name); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message, 1); + intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message); efree(message); } else { if (Z_LVAL_P(ele_value) > INT32_MAX || Z_LVAL_P(ele_value) < INT32_MIN) { - spprintf(&message, 0, "datefmt_format: value " ZEND_LONG_FMT " is out of " + spprintf(&message, 0, "value " ZEND_LONG_FMT " is out of " "bounds for a 32-bit integer in key '%s'", Z_LVAL_P(ele_value), key_name); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message, 1); + intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message); efree(message); } else { result = Z_LVAL_P(ele_value); @@ -121,8 +121,7 @@ static UDate internal_get_timestamp(IntlDateFormatter_object *dfo, &INTL_DATA_ERROR_CODE(dfo)); if (INTL_DATA_ERROR_CODE(dfo) != U_ZERO_ERROR) { - intl_errors_set(err, INTL_DATA_ERROR_CODE(dfo), "datefmt_format: " - "error cloning calendar", 0); + intl_errors_set(err, INTL_DATA_ERROR_CODE(dfo), "error cloning calendar"); return 0; } @@ -149,8 +148,6 @@ PHP_FUNCTION(datefmt_format) /* Parse parameters. */ if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oz", &object, IntlDateFormatter_ce_ptr, &zarg) == FAILURE) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: unable " - "to parse input params", 0 ); RETURN_THROWS(); } @@ -163,10 +160,9 @@ PHP_FUNCTION(datefmt_format) } timestamp = internal_get_timestamp(dfo, hash_arr); - INTL_METHOD_CHECK_STATUS(dfo, "datefmt_format: date formatting failed") + INTL_METHOD_CHECK_STATUS(dfo, "date formatting failed") } else { - timestamp = intl_zval_to_millis(zarg, INTL_DATA_ERROR_P(dfo), - "datefmt_format"); + timestamp = intl_zval_to_millis(zarg, INTL_DATA_ERROR_P(dfo)); if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { RETURN_FALSE; } diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp index 81490c62fd5e2..a5113ce4cf9e1 100644 --- a/ext/intl/dateformat/dateformat_format_object.cpp +++ b/ext/intl/dateformat/dateformat_format_object.cpp @@ -13,6 +13,7 @@ */ #include "../intl_cppshims.h" +#include #include #include @@ -70,10 +71,10 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) size_t locale_len; bool pattern = false; UDate date; - TimeZone *timeZone = NULL; + std::unique_ptr timeZone; UErrorCode status = U_ZERO_ERROR; - DateFormat *df = NULL; - Calendar *cal = NULL; + std::unique_ptr df; + std::unique_ptr cal; DateFormat::EStyle dateStyle = DateFormat::kDefault, timeStyle = DateFormat::kDefault; @@ -94,8 +95,8 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) HashTable *ht = Z_ARRVAL_P(format); if (zend_hash_num_elements(ht) != 2) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "datefmt_format_object: bad format; if array, it must have " - "two elements", 0); + "bad format; if array, it must have " + "two elements"); RETURN_FALSE; } @@ -105,13 +106,13 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) if (!valid_format(z)) { if (idx == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "datefmt_format_object: bad format; the date format (first " - "element of the array) is not valid", 0); + "bad format; the date format (first " + "element of the array) is not valid"); } else { ZEND_ASSERT(idx == 1 && "We checked that there are two elements above"); intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "datefmt_format_object: bad format; the time format (second " - "element of the array) is not valid", 0); + "bad format; the time format (second " + "element of the array) is not valid"); } RETURN_FALSE; } @@ -127,8 +128,7 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) } else if (Z_TYPE_P(format) == IS_LONG) { if (!valid_format(format)) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "datefmt_format_object: the date/time format type is invalid", - 0); + "the date/time format type is invalid"); RETURN_FALSE; } dateStyle = timeStyle = (DateFormat::EStyle)Z_LVAL_P(format); @@ -138,7 +138,7 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) } if (Z_STRLEN_P(format) == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "datefmt_format_object: the format is empty", 0); + "the format is empty"); RETURN_FALSE; } pattern = true; @@ -154,72 +154,58 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) Calendar *obj_cal = calendar_fetch_native_calendar(object); if (obj_cal == NULL) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "datefmt_format_object: bad IntlCalendar instance: " - "not initialized properly", 0); + "bad IntlCalendar instance: not initialized properly"); RETURN_FALSE; } - timeZone = obj_cal->getTimeZone().clone(); + timeZone = std::unique_ptr(obj_cal->getTimeZone().clone()); date = obj_cal->getTime(status); if (U_FAILURE(status)) { intl_error_set(NULL, status, - "datefmt_format_object: error obtaining instant from " - "IntlCalendar", 0); - RETVAL_FALSE; - goto cleanup; + "error obtaining instant from IntlCalendar"); + RETURN_FALSE; } - cal = obj_cal->clone(); + cal = std::unique_ptr(obj_cal->clone()); } else if (instanceof_function(instance_ce, php_date_get_interface_ce())) { - if (intl_datetime_decompose(object, &date, &timeZone, NULL, - "datefmt_format_object") == FAILURE) { + TimeZone *tz; + if (intl_datetime_decompose(object, &date, &tz, NULL) == FAILURE) { RETURN_FALSE; } - cal = new GregorianCalendar(Locale::createFromName(locale_str), status); + timeZone = std::unique_ptr(tz); + cal = std::unique_ptr(new GregorianCalendar(Locale::createFromName(locale_str), status)); if (U_FAILURE(status)) { - intl_error_set(NULL, status, - "datefmt_format_object: could not create GregorianCalendar", - 0); - RETVAL_FALSE; - goto cleanup; + intl_error_set(NULL, status, "could not create GregorianCalendar"); + RETURN_FALSE; } } else { - intl_error_set(NULL, status, "datefmt_format_object: the passed object " - "must be an instance of either IntlCalendar or DateTimeInterface", - 0); + intl_error_set(NULL, status, "the passed object must be an instance " + "of either IntlCalendar or DateTimeInterface"); RETURN_FALSE; } if (pattern) { StringPiece sp(Z_STRVAL_P(format)); - df = new SimpleDateFormat( + df = std::unique_ptr(new SimpleDateFormat( UnicodeString::fromUTF8(sp), Locale::createFromName(locale_str), - status); + status)); if (U_FAILURE(status)) { - intl_error_set(NULL, status, - "datefmt_format_object: could not create SimpleDateFormat", - 0); - RETVAL_FALSE; - goto cleanup; + intl_error_set(NULL, status, "could not create SimpleDateFormat"); + RETURN_FALSE; } } else { - df = DateFormat::createDateTimeInstance(dateStyle, timeStyle, - Locale::createFromName(locale_str)); + df = std::unique_ptr(DateFormat::createDateTimeInstance(dateStyle, timeStyle, + Locale::createFromName(locale_str))); if (df == NULL) { /* according to ICU sources, this should never happen */ - intl_error_set(NULL, status, - "datefmt_format_object: could not create DateFormat", - 0); - RETVAL_FALSE; - goto cleanup; + intl_error_set(NULL, status, "could not create DateFormat"); + RETURN_FALSE; } } //must be in this order (or have the cal adopt the tz) - df->adoptCalendar(cal); - cal = NULL; - df->adoptTimeZone(timeZone); - timeZone = NULL; + df->adoptCalendar(cal.release()); + df->adoptTimeZone(timeZone.release()); { zend_string *u8str; @@ -228,18 +214,9 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) u8str = intl_charFromString(result, &status); if (!u8str) { - intl_error_set(NULL, status, - "datefmt_format_object: error converting result to UTF-8", - 0); - RETVAL_FALSE; - goto cleanup; + intl_error_set(NULL, status, "error converting result to UTF-8"); + RETURN_FALSE; } RETVAL_STR(u8str); } - - -cleanup: - delete df; - delete timeZone; - delete cal; } diff --git a/ext/intl/dateformat/dateformat_helpers.cpp b/ext/intl/dateformat/dateformat_helpers.cpp index 2842c520a3092..18dc594dedddc 100644 --- a/ext/intl/dateformat/dateformat_helpers.cpp +++ b/ext/intl/dateformat/dateformat_helpers.cpp @@ -28,11 +28,10 @@ extern "C" { using icu::GregorianCalendar; -int datefmt_process_calendar_arg( +zend_result datefmt_process_calendar_arg( zend_object *calendar_obj, zend_long calendar_long, bool calendar_is_null, Locale const& locale, - const char *func_name, intl_error *err, Calendar*& cal, zend_long& cal_int_type, bool& calendar_owned + intl_error *err, Calendar*& cal, zend_long& cal_int_type, bool& calendar_owned ) { - char *msg; UErrorCode status = UErrorCode(); if (calendar_is_null) { @@ -45,13 +44,11 @@ int datefmt_process_calendar_arg( } else if (!calendar_obj) { zend_long v = calendar_long; if (v != (zend_long)UCAL_TRADITIONAL && v != (zend_long)UCAL_GREGORIAN) { - spprintf(&msg, 0, "%s: Invalid value for calendar type; it must be " - "one of IntlDateFormatter::TRADITIONAL (locale's default " - "calendar) or IntlDateFormatter::GREGORIAN. " - "Alternatively, it can be an IntlCalendar object", - func_name); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1); - efree(msg); + intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, + "Invalid value for calendar type; it must be one of " + "IntlDateFormatter::TRADITIONAL (locale's default calendar) or" + " IntlDateFormatter::GREGORIAN. Alternatively, it can be an " + "IntlCalendar object"); return FAILURE; } else if (v == (zend_long)UCAL_TRADITIONAL) { cal = Calendar::createInstance(locale, status); @@ -65,10 +62,7 @@ int datefmt_process_calendar_arg( } else if (calendar_obj) { cal = calendar_fetch_native_calendar(calendar_obj); if (cal == NULL) { - spprintf(&msg, 0, "%s: Found unconstructed IntlCalendar object", - func_name); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1); - efree(msg); + intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, "Found unconstructed IntlCalendar object"); return FAILURE; } calendar_owned = false; @@ -76,10 +70,8 @@ int datefmt_process_calendar_arg( cal_int_type = -1; } else { - spprintf(&msg, 0, "%s: Invalid calendar argument; should be an integer " - "or an IntlCalendar instance", func_name); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1); - efree(msg); + intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, + "Invalid calendar argument; should be an integer or an IntlCalendar instance"); return FAILURE; } @@ -87,9 +79,7 @@ int datefmt_process_calendar_arg( status = U_MEMORY_ALLOCATION_ERROR; } if (U_FAILURE(status)) { - spprintf(&msg, 0, "%s: Failure instantiating calendar", func_name); - intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1); - efree(msg); + intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, "Failure instantiating calendar"); return FAILURE; } diff --git a/ext/intl/dateformat/dateformat_helpers.h b/ext/intl/dateformat/dateformat_helpers.h index 4140eb730a2c6..b931d9667e5f1 100644 --- a/ext/intl/dateformat/dateformat_helpers.h +++ b/ext/intl/dateformat/dateformat_helpers.h @@ -30,9 +30,9 @@ using icu::Locale; using icu::Calendar; using icu::DateFormat; -int datefmt_process_calendar_arg( +zend_result datefmt_process_calendar_arg( zend_object *calendar_obj, zend_long calendar_long, bool calendar_is_null, Locale const& locale, - const char *func_name, intl_error *err, Calendar*& cal, zend_long& cal_int_type, bool& calendar_owned + intl_error *err, Calendar*& cal, zend_long& cal_int_type, bool& calendar_owned ); #endif /* DATEFORMAT_HELPERS_H */ diff --git a/ext/intl/dateformat/dateformat_parse.c b/ext/intl/dateformat/dateformat_parse.c index 2bdde08bcaced..b6e9f7c92eb6f 100644 --- a/ext/intl/dateformat/dateformat_parse.c +++ b/ext/intl/dateformat/dateformat_parse.c @@ -150,7 +150,7 @@ PHP_FUNCTION(datefmt_parse) zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp); if (ZEND_LONG_INT_OVFL(long_parse_pos)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0); + intl_error_set_custom_msg(NULL, "String index is out of valid range."); RETURN_FALSE; } parse_pos = (int32_t)long_parse_pos; @@ -193,7 +193,7 @@ PHP_METHOD(IntlDateFormatter, parseToCalendar) } if (ZEND_LONG_INT_OVFL(long_parse_pos)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0); + intl_error_set_custom_msg(NULL, "String index is out of valid range."); RETURN_FALSE; } parse_pos = (int32_t)long_parse_pos; @@ -232,7 +232,7 @@ PHP_FUNCTION(datefmt_localtime) zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp); if (ZEND_LONG_INT_OVFL(long_parse_pos)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0); + intl_error_set_custom_msg(NULL, "String index is out of valid range."); RETURN_FALSE; } parse_pos = (int32_t)long_parse_pos; diff --git a/ext/intl/dateformat/datepatterngenerator_methods.cpp b/ext/intl/dateformat/datepatterngenerator_methods.cpp index 1b659c7aa20ce..beaf10d9f5079 100644 --- a/ext/intl/dateformat/datepatterngenerator_methods.cpp +++ b/ext/intl/dateformat/datepatterngenerator_methods.cpp @@ -30,7 +30,7 @@ using icu::DateTimePatternGenerator; using icu::Locale; using icu::StringPiece; -static zend_result dtpg_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) +static zend_result dtpg_ctor(INTERNAL_FUNCTION_PARAMETERS) { char *locale_str; size_t locale_len = 0; @@ -44,15 +44,10 @@ static zend_result dtpg_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling * Z_PARAM_STRING_OR_NULL(locale_str, locale_len) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); - if (error_handling != NULL) { - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; - } - DTPATTERNGEN_METHOD_FETCH_OBJECT_NO_CHECK; if (dtpgo->dtpg != NULL) { - intl_errors_set(DTPATTERNGEN_ERROR_P(dtpgo), U_ILLEGAL_ARGUMENT_ERROR, "Cannot call constructor twice", 0); + intl_errors_set(DTPATTERNGEN_ERROR_P(dtpgo), U_ILLEGAL_ARGUMENT_ERROR, "Cannot call constructor twice"); return FAILURE; } @@ -68,8 +63,7 @@ static zend_result dtpg_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling * if (U_FAILURE(DTPATTERNGEN_ERROR_CODE(dtpgo))) { intl_error_set(NULL, DTPATTERNGEN_ERROR_CODE(dtpgo), - "Error creating DateTimePatternGenerator", - 0); + "Error creating DateTimePatternGenerator"); return FAILURE; } @@ -79,7 +73,7 @@ static zend_result dtpg_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling * U_CFUNC PHP_METHOD( IntlDatePatternGenerator, create ) { object_init_ex( return_value, IntlDatePatternGenerator_ce_ptr ); - if (dtpg_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { + if (dtpg_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { zval_ptr_dtor(return_value); RETURN_NULL(); } @@ -87,22 +81,19 @@ U_CFUNC PHP_METHOD( IntlDatePatternGenerator, create ) U_CFUNC PHP_METHOD( IntlDatePatternGenerator, __construct ) { - zend_error_handling error_handling; - bool error_handling_replaced = 0; + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; /* return_value param is being changed, therefore we will always return * NULL here */ return_value = ZEND_THIS; - if (dtpg_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) { - if (!EG(exception)) { - zend_string *err = intl_error_get_message(NULL); - zend_throw_exception(IntlException_ce_ptr, ZSTR_VAL(err), intl_error_get_code(NULL)); - zend_string_release_ex(err, 0); - } - } - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); + if (dtpg_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + ZEND_ASSERT(EG(exception)); } + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } diff --git a/ext/intl/formatter/formatter_arginfo.h b/ext/intl/formatter/formatter_arginfo.h index b872b0dc20f46..ce9de964e77b1 100644 --- a/ext/intl/formatter/formatter_arginfo.h +++ b/ext/intl/formatter/formatter_arginfo.h @@ -627,10 +627,7 @@ static zend_class_entry *register_class_NumberFormatter(void) zend_attribute *attribute_Deprecated_const_TYPE_CURRENCY_0 = zend_add_class_constant_attribute(class_entry, const_TYPE_CURRENCY, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_const_TYPE_CURRENCY_0_arg0; - zend_string *attribute_Deprecated_const_TYPE_CURRENCY_0_arg0_str = zend_string_init("8.3", strlen("8.3"), 1); - ZVAL_STR(&attribute_Deprecated_const_TYPE_CURRENCY_0_arg0, attribute_Deprecated_const_TYPE_CURRENCY_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_TYPE_CURRENCY_0->args[0].value, &attribute_Deprecated_const_TYPE_CURRENCY_0_arg0); + ZVAL_STR(&attribute_Deprecated_const_TYPE_CURRENCY_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); attribute_Deprecated_const_TYPE_CURRENCY_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); return class_entry; diff --git a/ext/intl/formatter/formatter_attr.c b/ext/intl/formatter/formatter_attr.c index 874984f5405f0..a7cafcf5f9733 100644 --- a/ext/intl/formatter/formatter_attr.c +++ b/ext/intl/formatter/formatter_attr.c @@ -226,7 +226,7 @@ PHP_FUNCTION( numfmt_get_symbol ) } if(symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_get_symbol: invalid symbol value", 0 ); + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid symbol value"); RETURN_FALSE; } @@ -268,7 +268,7 @@ PHP_FUNCTION( numfmt_set_symbol ) } if (symbol >= UNUM_FORMAT_SYMBOL_COUNT || symbol < 0) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "numfmt_set_symbol: invalid symbol value", 0 ); + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid symbol value"); RETURN_FALSE; } @@ -355,7 +355,7 @@ PHP_FUNCTION( numfmt_set_pattern ) if (U_FAILURE(INTL_DATA_ERROR_CODE(nfo))) { char *msg; spprintf(&msg, 0, "Error setting pattern value at line %d, offset %d", spattern_error.line, spattern_error.offset); - intl_errors_set_custom_msg(INTL_DATA_ERROR_P(nfo), msg, 1); + intl_errors_set_custom_msg(INTL_DATA_ERROR_P(nfo), msg); efree(msg); RETURN_FALSE; } diff --git a/ext/intl/formatter/formatter_format.c b/ext/intl/formatter/formatter_format.c index 0323757ed8620..5be732dde77e8 100644 --- a/ext/intl/formatter/formatter_format.c +++ b/ext/intl/formatter/formatter_format.c @@ -104,7 +104,7 @@ PHP_FUNCTION( numfmt_format ) INTL_METHOD_CHECK_STATUS( nfo, "Number formatting failed" ); break; case FORMAT_TYPE_CURRENCY: - if (getThis()) { + if (hasThis()) { const char *space; const char *class_name = get_active_class_name(&space); zend_argument_value_error(2, "cannot be NumberFormatter::TYPE_CURRENCY constant, " @@ -164,7 +164,7 @@ PHP_FUNCTION( numfmt_format_currency ) if( U_FAILURE( INTL_DATA_ERROR_CODE((nfo)) ) ) { intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((nfo)) ); - intl_errors_set_custom_msg( INTL_DATA_ERROR_P(nfo), "Number formatting failed", 0 ); + intl_errors_set_custom_msg( INTL_DATA_ERROR_P(nfo), "Number formatting failed"); RETVAL_FALSE; if (formatted != format_buf) { efree(formatted); diff --git a/ext/intl/formatter/formatter_main.c b/ext/intl/formatter/formatter_main.c index 6f8fb98d21434..d6d69f57277f9 100644 --- a/ext/intl/formatter/formatter_main.c +++ b/ext/intl/formatter/formatter_main.c @@ -24,7 +24,7 @@ #include "intl_convert.h" /* {{{ */ -static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) +static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS) { char* locale; char* pattern = NULL; @@ -41,11 +41,6 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_ Z_PARAM_STRING_OR_NULL(pattern, pattern_len) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); - if (error_handling != NULL) { - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; - } - INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); object = return_value; FORMATTER_METHOD_FETCH_OBJECT_NO_CHECK; @@ -57,7 +52,7 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_ /* Convert pattern (if specified) to UTF-16. */ if(pattern && pattern_len) { intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(nfo)); - INTL_CTOR_CHECK_STATUS(nfo, "numfmt_create: error converting pattern to UTF-16"); + INTL_CTOR_CHECK_STATUS(nfo, "error converting pattern to UTF-16"); } if(locale_len == 0) { @@ -69,14 +64,20 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_ return FAILURE; } - /* Create an ICU number formatter. */ - FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, locale, NULL, &INTL_DATA_ERROR_CODE(nfo)); + char* canonicalized_locale = canonicalize_locale_string(locale); + const char* final_locale = canonicalized_locale ? canonicalized_locale : locale; + + FORMATTER_OBJECT(nfo) = unum_open(style, spattern, spattern_len, final_locale, NULL, &INTL_DATA_ERROR_CODE(nfo)); - if(spattern) { + if (spattern) { efree(spattern); } + + if (canonicalized_locale) { + efree(canonicalized_locale); + } - INTL_CTOR_CHECK_STATUS(nfo, "numfmt_create: number formatter creation failed"); + INTL_CTOR_CHECK_STATUS(nfo, "number formatter creation failed"); return SUCCESS; } /* }}} */ @@ -85,7 +86,7 @@ static int numfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_ PHP_FUNCTION( numfmt_create ) { object_init_ex( return_value, NumberFormatter_ce_ptr ); - if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { + if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { zval_ptr_dtor(return_value); RETURN_NULL(); } @@ -95,18 +96,17 @@ PHP_FUNCTION( numfmt_create ) /* {{{ NumberFormatter object constructor. */ PHP_METHOD( NumberFormatter, __construct ) { - zend_error_handling error_handling; - bool error_handling_replaced = 0; + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; return_value = ZEND_THIS; - if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) { - if (!EG(exception)) { - zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); - } - } - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); + if (numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + ZEND_ASSERT(EG(exception)); } + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } /* }}} */ diff --git a/ext/intl/formatter/formatter_parse.c b/ext/intl/formatter/formatter_parse.c index 9939900650408..ba8307419b4cf 100644 --- a/ext/intl/formatter/formatter_parse.c +++ b/ext/intl/formatter/formatter_parse.c @@ -86,7 +86,7 @@ PHP_FUNCTION( numfmt_parse ) RETVAL_DOUBLE(val_double); break; case FORMAT_TYPE_CURRENCY: - if (getThis()) { + if (hasThis()) { const char *space; const char *class_name = get_active_class_name(&space); zend_argument_value_error(2, "cannot be NumberFormatter::TYPE_CURRENCY constant, " diff --git a/ext/intl/grapheme/grapheme_string.c b/ext/intl/grapheme/grapheme_string.c index 34dd2ed369cfc..28d3130c3959d 100644 --- a/ext/intl/grapheme/grapheme_string.c +++ b/ext/intl/grapheme/grapheme_string.c @@ -57,7 +57,7 @@ PHP_FUNCTION(grapheme_strlen) intl_error_set_code( NULL, status ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); + intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16"); if (ustring) { efree( ustring ); } @@ -81,19 +81,20 @@ PHP_FUNCTION(grapheme_strlen) /* {{{ Find position of first occurrence of a string within another */ PHP_FUNCTION(grapheme_strpos) { - char *haystack, *needle; - size_t haystack_len, needle_len; + char *haystack, *needle, *locale = ""; + size_t haystack_len, needle_len, locale_len = 0; const char *found; zend_long loffset = 0; int32_t offset = 0; size_t noffset = 0; zend_long ret_pos; - ZEND_PARSE_PARAMETERS_START(2, 3) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_STRING(haystack, haystack_len) Z_PARAM_STRING(needle, needle_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(loffset) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if ( OUTSIDE_STRING(loffset, haystack_len) ) { @@ -121,7 +122,7 @@ PHP_FUNCTION(grapheme_strpos) } /* do utf16 part of the strpos */ - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 0 /* fIgnoreCase */, 0 /* last */ ); + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* fIgnoreCase */ 0, /* last */ 0, locale); if ( ret_pos >= 0 ) { RETURN_LONG(ret_pos); @@ -134,19 +135,20 @@ PHP_FUNCTION(grapheme_strpos) /* {{{ Find position of first occurrence of a string within another, ignoring case differences */ PHP_FUNCTION(grapheme_stripos) { - char *haystack, *needle; - size_t haystack_len, needle_len; + char *haystack, *needle, *locale = ""; + size_t haystack_len, needle_len, locale_len = 0; const char *found; zend_long loffset = 0; int32_t offset = 0; zend_long ret_pos; int is_ascii; - ZEND_PARSE_PARAMETERS_START(2, 3) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_STRING(haystack, haystack_len) Z_PARAM_STRING(needle, needle_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(loffset) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if ( OUTSIDE_STRING(loffset, haystack_len) ) { @@ -185,7 +187,7 @@ PHP_FUNCTION(grapheme_stripos) } /* do utf16 part of the strpos */ - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 1 /* fIgnoreCase */, 0 /*last */ ); + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* fIgnoreCase */ 1, /*last */ 0, locale); if ( ret_pos >= 0 ) { RETURN_LONG(ret_pos); @@ -200,17 +202,19 @@ PHP_FUNCTION(grapheme_stripos) PHP_FUNCTION(grapheme_strrpos) { char *haystack, *needle; - size_t haystack_len, needle_len; + char *locale = ""; + size_t haystack_len, needle_len, locale_len = 0; zend_long loffset = 0; int32_t offset = 0; zend_long ret_pos; int is_ascii; - ZEND_PARSE_PARAMETERS_START(2, 3) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_STRING(haystack, haystack_len) Z_PARAM_STRING(needle, needle_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(loffset) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if ( OUTSIDE_STRING(loffset, haystack_len) ) { @@ -242,7 +246,7 @@ PHP_FUNCTION(grapheme_strrpos) /* else we need to continue via utf16 */ } - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 0 /* f_ignore_case */, 1/* last */); + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* f_ignore_case */ 0, /* last */ 1, locale); if ( ret_pos >= 0 ) { RETURN_LONG(ret_pos); @@ -257,18 +261,19 @@ PHP_FUNCTION(grapheme_strrpos) /* {{{ Find position of last occurrence of a string within another, ignoring case */ PHP_FUNCTION(grapheme_strripos) { - char *haystack, *needle; - size_t haystack_len, needle_len; + char *haystack, *needle, *locale = ""; + size_t haystack_len, needle_len, locale_len = 0; zend_long loffset = 0; int32_t offset = 0; zend_long ret_pos; int is_ascii; - ZEND_PARSE_PARAMETERS_START(2, 3) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_STRING(haystack, haystack_len) Z_PARAM_STRING(needle, needle_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(loffset) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if ( OUTSIDE_STRING(loffset, haystack_len) ) { @@ -309,7 +314,7 @@ PHP_FUNCTION(grapheme_strripos) /* else we need to continue via utf16 */ } - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, 1 /* f_ignore_case */, 1 /*last */); + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, offset, NULL, /* f_ignore_case */ 1, /*last */ 1, locale); if ( ret_pos >= 0 ) { RETURN_LONG(ret_pos); @@ -324,10 +329,10 @@ PHP_FUNCTION(grapheme_strripos) /* {{{ Returns part of a string */ PHP_FUNCTION(grapheme_substr) { - char *str; + char *str, *locale = ""; zend_string *u8_sub_str; UChar *ustr; - size_t str_len; + size_t str_len, locale_len = 0; int32_t ustr_len; zend_long lstart = 0, length = 0; int32_t start = 0; @@ -339,11 +344,12 @@ PHP_FUNCTION(grapheme_substr) int32_t (*iter_func)(UBreakIterator *); bool no_length = true; - ZEND_PARSE_PARAMETERS_START(2, 3) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_STRING(str, str_len) Z_PARAM_LONG(lstart) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(length, no_length) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if (lstart < INT32_MIN || lstart > INT32_MAX) { @@ -370,7 +376,7 @@ PHP_FUNCTION(grapheme_substr) grapheme_substr_ascii(str, str_len, start, (int32_t)length, &sub_str, &asub_str_len); if ( NULL == sub_str ) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_substr: invalid parameters", 1 ); + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "invalid parameters"); RETURN_FALSE; } @@ -387,7 +393,7 @@ PHP_FUNCTION(grapheme_substr) intl_error_set_code( NULL, status ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); + intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16"); if (ustr) { efree( ustr ); } @@ -455,7 +461,7 @@ PHP_FUNCTION(grapheme_substr) intl_error_set_code( NULL, status ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 0 ); + intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8"); RETURN_FALSE; } @@ -524,7 +530,7 @@ PHP_FUNCTION(grapheme_substr) intl_error_set_code( NULL, status ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8", 0 ); + intl_error_set_custom_msg( NULL, "Error converting output string to UTF-8"); RETURN_FALSE; } @@ -537,17 +543,18 @@ PHP_FUNCTION(grapheme_substr) /* {{{ strstr_common_handler */ static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_case) { - char *haystack, *needle; + char *haystack, *needle, *locale = ""; const char *found; - size_t haystack_len, needle_len; + size_t haystack_len, needle_len, locale_len = 0; int32_t ret_pos, uchar_pos; bool part = false; - ZEND_PARSE_PARAMETERS_START(2, 3) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_STRING(haystack, haystack_len) Z_PARAM_STRING(needle, needle_len) Z_PARAM_OPTIONAL Z_PARAM_BOOL(part) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if ( !f_ignore_case ) { @@ -574,7 +581,7 @@ static void strstr_common_handler(INTERNAL_FUNCTION_PARAMETERS, int f_ignore_cas } /* need to work in utf16 */ - ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, 0, &uchar_pos, f_ignore_case, 0 /*last */ ); + ret_pos = grapheme_strpos_utf16(haystack, haystack_len, needle, needle_len, 0, &uchar_pos, f_ignore_case, /* last */ 0, locale); if ( ret_pos < 0 ) { RETURN_FALSE; @@ -747,7 +754,7 @@ PHP_FUNCTION(grapheme_extract) } if ( lstart > INT32_MAX || lstart < 0 || (size_t)lstart >= str_len ) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "grapheme_extract: start not contained in string", 0 ); + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "start not contained in string"); RETURN_FALSE; } @@ -779,7 +786,7 @@ PHP_FUNCTION(grapheme_extract) start++; if ( pstr >= str_end ) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, - "grapheme_extract: invalid input string", 0 ); + "grapheme_extract: invalid input string"); RETURN_FALSE; } @@ -808,7 +815,7 @@ PHP_FUNCTION(grapheme_extract) intl_error_set_code( NULL, status ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error opening UTF-8 text", 0 ); + intl_error_set_custom_msg( NULL, "Error opening UTF-8 text"); RETURN_FALSE; } @@ -870,7 +877,7 @@ PHP_FUNCTION(grapheme_str_split) intl_error_set_code( NULL, ustatus ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error opening UTF-8 text", 0 ); + intl_error_set_custom_msg( NULL, "Error opening UTF-8 text"); RETURN_FALSE; } @@ -919,14 +926,17 @@ PHP_FUNCTION(grapheme_levenshtein) zend_long cost_ins = 1; zend_long cost_rep = 1; zend_long cost_del = 1; + char *locale = ""; + size_t locale_len = 0; - ZEND_PARSE_PARAMETERS_START(2, 5) + ZEND_PARSE_PARAMETERS_START(2, 6) Z_PARAM_STR(string1) Z_PARAM_STR(string2) Z_PARAM_OPTIONAL Z_PARAM_LONG(cost_ins) Z_PARAM_LONG(cost_rep) Z_PARAM_LONG(cost_del) + Z_PARAM_PATH(locale, locale_len) ZEND_PARSE_PARAMETERS_END(); if (cost_ins <= 0 || cost_ins > UINT_MAX / 4) { @@ -974,7 +984,7 @@ PHP_FUNCTION(grapheme_levenshtein) if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); - intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); + intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16"); RETVAL_FALSE; goto out_ustring1; } @@ -984,7 +994,7 @@ PHP_FUNCTION(grapheme_levenshtein) if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); - intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16", 0); + intl_error_set_custom_msg(NULL, "Error converting input string to UTF-16"); RETVAL_FALSE; goto out_ustring2; } @@ -1013,7 +1023,7 @@ PHP_FUNCTION(grapheme_levenshtein) bi1 = grapheme_get_break_iterator(u_break_iterator_buffer1, &ustatus); if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); - intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #1 ($string1)", 0); + intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #1 ($string1)"); RETVAL_FALSE; goto out_bi1; } @@ -1021,7 +1031,7 @@ PHP_FUNCTION(grapheme_levenshtein) bi2 = grapheme_get_break_iterator(u_break_iterator_buffer2, &ustatus); if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); - intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #2 ($string2)", 0); + intl_error_set_custom_msg(NULL, "Error on grapheme_get_break_iterator for argument #2 ($string2)"); RETVAL_FALSE; goto out_bi2; } @@ -1030,7 +1040,7 @@ PHP_FUNCTION(grapheme_levenshtein) if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); - intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #1 ($string1)", 0); + intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #1 ($string1)"); RETVAL_FALSE; goto out_bi2; } @@ -1039,15 +1049,15 @@ PHP_FUNCTION(grapheme_levenshtein) if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); - intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #2 ($string2)", 0); + intl_error_set_custom_msg(NULL, "Error on ubrk_setText for argument #2 ($string2)"); RETVAL_FALSE; goto out_bi2; } - UCollator *collator = ucol_open("", &ustatus); + UCollator *collator = ucol_open(locale, &ustatus); if (U_FAILURE(ustatus)) { intl_error_set_code(NULL, ustatus); - intl_error_set_custom_msg(NULL, "Error on ucol_open", 0); + intl_error_set_custom_msg(NULL, "Error on ucol_open"); RETVAL_FALSE; goto out_collator; } diff --git a/ext/intl/grapheme/grapheme_util.c b/ext/intl/grapheme/grapheme_util.c index 501b9dfb221d0..825eea9468cb3 100644 --- a/ext/intl/grapheme/grapheme_util.c +++ b/ext/intl/grapheme/grapheme_util.c @@ -87,14 +87,14 @@ void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char #define STRPOS_CHECK_STATUS(status, error) \ if ( U_FAILURE( (status) ) ) { \ intl_error_set_code( NULL, (status) ); \ - intl_error_set_custom_msg( NULL, (error), 0 ); \ + intl_error_set_custom_msg( NULL, (error)); \ ret_pos = -1; \ goto finish; \ } /* {{{ grapheme_strpos_utf16 - strrpos using utf16*/ -int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case, int last) +int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int32_t *puchar_pos, int f_ignore_case, int last, const char* locale) { UChar *uhaystack = NULL, *uneedle = NULL; int32_t uhaystack_len = 0, uneedle_len = 0, char_pos, ret_pos, offset_pos = 0; @@ -136,7 +136,7 @@ int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, } status = U_ZERO_ERROR; - src = usearch_open(uneedle, uneedle_len, uhaystack, uhaystack_len, "", bi, &status); + src = usearch_open(uneedle, uneedle_len, uhaystack, uhaystack_len, locale, bi, &status); STRPOS_CHECK_STATUS(status, "Error creating search object"); if(f_ignore_case) { diff --git a/ext/intl/grapheme/grapheme_util.h b/ext/intl/grapheme/grapheme_util.h index d03194621acf3..9d276a9dcfe26 100644 --- a/ext/intl/grapheme/grapheme_util.h +++ b/ext/intl/grapheme/grapheme_util.h @@ -25,8 +25,8 @@ zend_long grapheme_ascii_check(const unsigned char *day, size_t len); void grapheme_substr_ascii(char *str, size_t str_len, int32_t f, int32_t l, char **sub_str, int32_t *sub_str_len); zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset); -int32_t grapheme_strrpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int f_ignore_case); -int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int *puchar_pos, int f_ignore_case, int last); +int32_t grapheme_strrpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int f_ignore_case, const char *locale); +int32_t grapheme_strpos_utf16(char *haystack, size_t haystack_len, char *needle, size_t needle_len, int32_t offset, int *puchar_pos, int f_ignore_case, int last, const char *locale); int32_t grapheme_split_string(const UChar *text, int32_t text_length, int boundary_array[], int boundary_array_len ); diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.cpp similarity index 95% rename from ext/intl/idn/idn.c rename to ext/intl/idn/idn.cpp index cd4546ad7f8bb..6c7e4d8c6d683 100644 --- a/ext/intl/idn/idn.c +++ b/ext/intl/idn/idn.cpp @@ -20,13 +20,17 @@ #include #endif -#include - +extern "C" { +#include "../php_intl.h" +} #include #include #include "idn.h" + +extern "C" { #include "intl_error.h" +} /* }}} */ enum { @@ -39,12 +43,7 @@ static zend_result php_intl_idn_check_status(UErrorCode err, const char *msg) { intl_error_set_code(NULL, err); if (U_FAILURE(err)) { - char *buff; - spprintf(&buff, 0, "%s: %s", - get_active_function_name(), - msg); - intl_error_set_custom_msg(NULL, buff, 1); - efree(buff); + intl_error_set_custom_msg(NULL, msg); return FAILURE; } @@ -145,7 +144,7 @@ static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode) } /* {{{ Converts an Unicode domain to ASCII representation, as defined in the IDNA RFC */ -PHP_FUNCTION(idn_to_ascii) +U_CFUNC PHP_FUNCTION(idn_to_ascii) { php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_ASCII); } @@ -153,7 +152,7 @@ PHP_FUNCTION(idn_to_ascii) /* {{{ Converts an ASCII representation of the domain to Unicode (UTF-8), as defined in the IDNA RFC */ -PHP_FUNCTION(idn_to_utf8) +U_CFUNC PHP_FUNCTION(idn_to_utf8) { php_intl_idn_handoff(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTL_IDN_TO_UTF8); } diff --git a/ext/intl/intl_data.h b/ext/intl/intl_data.h index 23320a9ff113e..c818427e07e1e 100644 --- a/ext/intl/intl_data.h +++ b/ext/intl/intl_data.h @@ -48,7 +48,7 @@ typedef struct _intl_data { intl_error_set_code( NULL, (err) ); \ if( U_FAILURE((err)) ) \ { \ - intl_error_set_custom_msg( NULL, msg, 0 ); \ + intl_error_set_custom_msg( NULL, msg); \ RETURN_FALSE; \ } @@ -57,7 +57,7 @@ typedef struct _intl_data { intl_error_set_code( NULL, (err) ); \ if( U_FAILURE((err)) ) \ { \ - intl_error_set_custom_msg( NULL, msg, 0 ); \ + intl_error_set_custom_msg( NULL, msg); \ RETURN_NULL(); \ } @@ -67,7 +67,7 @@ typedef struct _intl_data { intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((obj)) ); \ if( U_FAILURE( INTL_DATA_ERROR_CODE((obj)) ) ) \ { \ - intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg, 0 ); \ + intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg); \ RETURN_FALSE; \ } @@ -76,7 +76,7 @@ typedef struct _intl_data { intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((obj)) ); \ if( U_FAILURE( INTL_DATA_ERROR_CODE((obj)) ) ) \ { \ - intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg, 0 ); \ + intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg); \ RETVAL_FALSE; \ goto label; \ } @@ -86,7 +86,7 @@ typedef struct _intl_data { intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((obj)) ); \ if( U_FAILURE( INTL_DATA_ERROR_CODE((obj)) ) ) \ { \ - intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg, 0 ); \ + intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg); \ zval_ptr_dtor(return_value); \ RETURN_NULL(); \ } @@ -96,7 +96,7 @@ typedef struct _intl_data { intl_error_set_code( NULL, INTL_DATA_ERROR_CODE((obj)) ); \ if( U_FAILURE( INTL_DATA_ERROR_CODE((obj)) ) ) \ { \ - intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg, 0 ); \ + intl_errors_set_custom_msg( INTL_DATA_ERROR_P((obj)), msg); \ return FAILURE; \ } @@ -117,7 +117,7 @@ typedef struct _intl_data { if((locale_len) > INTL_MAX_LOCALE_LEN) { \ char *_msg; \ spprintf(&_msg, 0, "Locale string too long, should be no longer than %d characters", INTL_MAX_LOCALE_LEN); \ - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, _msg, 1); \ + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, _msg); \ efree(_msg); \ RETURN_NULL(); \ } @@ -126,7 +126,7 @@ typedef struct _intl_data { if((locale_len) > INTL_MAX_LOCALE_LEN) { \ char *_msg; \ spprintf(&_msg, 0, "Locale string too long, should be no longer than %d characters", INTL_MAX_LOCALE_LEN); \ - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, _msg, 1); \ + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, _msg); \ efree(_msg); \ return FAILURE; \ } diff --git a/ext/intl/intl_error.c b/ext/intl/intl_error.c index a1c3a9efb2d4b..be6e53fb5439a 100644 --- a/ext/intl/intl_error.c +++ b/ext/intl/intl_error.c @@ -42,12 +42,10 @@ static void intl_free_custom_error_msg( intl_error* err ) if( !err && !( err = intl_g_error_get( ) ) ) return; - if(err->free_custom_error_message ) { - efree( err->custom_error_message ); + if (err->custom_error_message) { + zend_string_release_ex(err->custom_error_message, false); + err->custom_error_message = NULL; } - - err->custom_error_message = NULL; - err->free_custom_error_message = 0; } /* }}} */ @@ -70,7 +68,6 @@ void intl_error_init( intl_error* err ) err->code = U_ZERO_ERROR; err->custom_error_message = NULL; - err->free_custom_error_message = 0; } /* }}} */ @@ -87,28 +84,41 @@ void intl_error_reset( intl_error* err ) /* }}} */ /* {{{ Set last error message to msg copying it if needed. */ -void intl_error_set_custom_msg( intl_error* err, const char* msg, int copyMsg ) +void intl_error_set_custom_msg( intl_error* err, const char* msg) { - if( !msg ) + /* See ext/intl/tests/bug70451.phpt and uchar.c:zif_IntlChar_charFromName */ + if (UNEXPECTED(msg == NULL)) { return; + } + + zend_string *method_or_func = get_active_function_or_method_name(); + zend_string *prefixed_message = zend_string_concat3( + ZSTR_VAL(method_or_func), ZSTR_LEN(method_or_func), + ZEND_STRL("(): "), + msg, strlen(msg) + ); + zend_string_release_ex(method_or_func, false); if( !err ) { - if( INTL_G( error_level ) ) + if (INTL_G(error_level)) { + /* Docref will prefix the function/method for us, so use original message */ php_error_docref( NULL, INTL_G( error_level ), "%s", msg ); - if( INTL_G( use_exceptions ) ) - zend_throw_exception_ex( IntlException_ce_ptr, 0, "%s", msg ); + } + if (INTL_G(use_exceptions)) { + /* Use this variant as we have a zend_string already */ + zend_throw_error_exception(IntlException_ce_ptr, prefixed_message, 0, 0); + } } - if( !err && !( err = intl_g_error_get( ) ) ) + if (!err && !(err = intl_g_error_get() )) { + zend_string_release_ex(prefixed_message, false); return; + } /* Free previous message if any */ intl_free_custom_error_msg( err ); - /* Mark message copied if any */ - err->free_custom_error_message = copyMsg; - /* Set user's error text message */ - err->custom_error_message = copyMsg ? estrdup( msg ) : (char *) msg; + err->custom_error_message = prefixed_message; } /* }}} */ @@ -116,21 +126,22 @@ void intl_error_set_custom_msg( intl_error* err, const char* msg, int copyMsg ) zend_string * intl_error_get_message( intl_error* err ) { const char *uErrorName = NULL; - zend_string *errMessage = 0; + zend_string *errMessage = NULL; if( !err && !( err = intl_g_error_get( ) ) ) return ZSTR_EMPTY_ALLOC(); uErrorName = u_errorName( err->code ); + size_t uErrorLen = strlen(uErrorName); /* Format output string */ - if( err->custom_error_message ) - { - errMessage = strpprintf(0, "%s: %s", err->custom_error_message, uErrorName ); - } - else - { - errMessage = strpprintf(0, "%s", uErrorName ); + if (err->custom_error_message) { + errMessage = zend_string_concat3( + ZSTR_VAL(err->custom_error_message), ZSTR_LEN(err->custom_error_message), + ZEND_STRL(": "), + uErrorName, uErrorLen); + } else { + errMessage = zend_string_init(uErrorName, strlen(uErrorName), false); } return errMessage; @@ -158,18 +169,18 @@ UErrorCode intl_error_get_code( intl_error* err ) /* }}} */ /* {{{ Set error code and message. */ -void intl_error_set( intl_error* err, UErrorCode code, const char* msg, int copyMsg ) +void intl_error_set( intl_error* err, UErrorCode code, const char* msg) { intl_error_set_code( err, code ); - intl_error_set_custom_msg( err, msg, copyMsg ); + intl_error_set_custom_msg( err, msg); } /* }}} */ /* {{{ Set error code and message. */ -void intl_errors_set( intl_error* err, UErrorCode code, const char* msg, int copyMsg ) +void intl_errors_set( intl_error* err, UErrorCode code, const char* msg) { intl_errors_set_code( err, code ); - intl_errors_set_custom_msg( err, msg, copyMsg ); + intl_errors_set_custom_msg( err, msg); } /* }}} */ @@ -184,12 +195,12 @@ void intl_errors_reset( intl_error* err ) /* }}} */ /* {{{ */ -void intl_errors_set_custom_msg( intl_error* err, const char* msg, int copyMsg ) +void intl_errors_set_custom_msg(intl_error* err, const char* msg) { if(err) { - intl_error_set_custom_msg( err, msg, copyMsg ); + intl_error_set_custom_msg( err, msg); } - intl_error_set_custom_msg( NULL, msg, copyMsg ); + intl_error_set_custom_msg( NULL, msg); } /* }}} */ diff --git a/ext/intl/intl_error.h b/ext/intl/intl_error.h index 74bf0d8a43eee..8a9bff0b271c0 100644 --- a/ext/intl/intl_error.h +++ b/ext/intl/intl_error.h @@ -23,26 +23,25 @@ #define INTL_ERROR_CODE(e) (e).code -typedef struct _intl_error { - UErrorCode code; - int free_custom_error_message; - char* custom_error_message; +typedef struct { + zend_string *custom_error_message; + UErrorCode code; } intl_error; intl_error* intl_error_create( void ); void intl_error_init( intl_error* err ); void intl_error_reset( intl_error* err ); void intl_error_set_code( intl_error* err, UErrorCode err_code ); -void intl_error_set_custom_msg( intl_error* err, const char* msg, int copyMsg ); -void intl_error_set( intl_error* err, UErrorCode code, const char* msg, int copyMsg ); +void intl_error_set_custom_msg( intl_error* err, const char* msg); +void intl_error_set( intl_error* err, UErrorCode code, const char* msg); UErrorCode intl_error_get_code( intl_error* err ); zend_string* intl_error_get_message( intl_error* err ); // Wrappers to synchonize object's and global error structures. void intl_errors_reset( intl_error* err ); -void intl_errors_set_custom_msg( intl_error* err, const char* msg, int copyMsg ); +void intl_errors_set_custom_msg( intl_error* err, const char* msg); void intl_errors_set_code( intl_error* err, UErrorCode err_code ); -void intl_errors_set( intl_error* err, UErrorCode code, const char* msg, int copyMsg ); +void intl_errors_set( intl_error* err, UErrorCode code, const char* msg); // Other error helpers smart_str intl_parse_error_to_string( UParseError* pe ); diff --git a/ext/intl/listformatter/listformatter_class.c b/ext/intl/listformatter/listformatter_class.c index 1fe8da554a1ca..1aa849370ab8f 100644 --- a/ext/intl/listformatter/listformatter_class.c +++ b/ext/intl/listformatter/listformatter_class.c @@ -72,7 +72,7 @@ PHP_METHOD(IntlListFormatter, __construct) } if (locale_len > INTL_MAX_LOCALE_LEN) { - zend_argument_value_error(1, "Locale string too long, should be no longer than %d characters", INTL_MAX_LOCALE_LEN); + zend_argument_value_error(1, "must be less than or equal to %d characters", INTL_MAX_LOCALE_LEN); RETURN_THROWS(); } @@ -109,7 +109,7 @@ PHP_METHOD(IntlListFormatter, __construct) #endif if (U_FAILURE(status)) { - intl_error_set(NULL, status, "Constructor failed", 0); + intl_error_set(NULL, status, "Constructor failed"); zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); RETURN_THROWS(); } @@ -135,9 +135,9 @@ PHP_METHOD(IntlListFormatter, format) zval *val; ZEND_HASH_FOREACH_VAL(ht, val) { - zend_string *str_val; + zend_string *str_val, *tmp_str; - str_val = zval_get_string(val); + str_val = zval_get_tmp_string(val, &tmp_str); // Convert PHP string to UTF-16 UChar *ustr = NULL; @@ -145,7 +145,7 @@ PHP_METHOD(IntlListFormatter, format) UErrorCode status = U_ZERO_ERROR; intl_convert_utf8_to_utf16(&ustr, &ustr_len, ZSTR_VAL(str_val), ZSTR_LEN(str_val), &status); - zend_string_release(str_val); + zend_tmp_string_release(tmp_str); if (U_FAILURE(status)) { // We can't use goto cleanup because items and itemLengths are incompletely allocated @@ -154,7 +154,7 @@ PHP_METHOD(IntlListFormatter, format) } efree(items); efree(itemLengths); - intl_error_set(NULL, status, "Failed to convert string to UTF-16", 0); + intl_error_set(NULL, status, "Failed to convert string to UTF-16"); RETURN_FALSE; } @@ -170,7 +170,7 @@ PHP_METHOD(IntlListFormatter, format) resultLength = ulistfmt_format(LISTFORMATTER_OBJECT(obj), items, itemLengths, count, NULL, 0, &status); if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) { - intl_error_set(NULL, status, "Failed to format list", 0); + intl_error_set(NULL, status, "Failed to format list"); RETVAL_FALSE; goto cleanup; } @@ -184,7 +184,7 @@ PHP_METHOD(IntlListFormatter, format) if (result) { efree(result); } - intl_error_set(NULL, status, "Failed to format list", 0); + intl_error_set(NULL, status, "Failed to format list"); RETVAL_FALSE; goto cleanup; } @@ -194,7 +194,7 @@ PHP_METHOD(IntlListFormatter, format) efree(result); if (!ret) { - intl_error_set(NULL, status, "Failed to convert result to UTF-8", 0); + intl_error_set(NULL, status, "Failed to convert result to UTF-8"); RETVAL_FALSE; } else { RETVAL_NEW_STR(ret); diff --git a/ext/intl/locale/locale.c b/ext/intl/locale/locale.cpp similarity index 100% rename from ext/intl/locale/locale.c rename to ext/intl/locale/locale.cpp diff --git a/ext/intl/locale/locale_class.c b/ext/intl/locale/locale_class.cpp similarity index 95% rename from ext/intl/locale/locale_class.c rename to ext/intl/locale/locale_class.cpp index cbde2a5fb0701..75fde45d53d60 100644 --- a/ext/intl/locale/locale_class.c +++ b/ext/intl/locale/locale_class.cpp @@ -13,11 +13,13 @@ */ #include +extern "C" { #include "php_intl.h" #include "intl_error.h" #include "locale_class.h" #include "locale.h" #include "locale_arginfo.h" +} zend_class_entry *Locale_ce_ptr = NULL; @@ -28,7 +30,7 @@ zend_class_entry *Locale_ce_ptr = NULL; /* {{{ locale_register_Locale_class * Initialize 'Locale' class */ -void locale_register_Locale_class( void ) +U_CFUNC void locale_register_Locale_class( void ) { /* Create and register 'Locale' class. */ Locale_ce_ptr = register_class_Locale(); diff --git a/ext/intl/locale/locale_class.h b/ext/intl/locale/locale_class.h index aa339d75db9b0..64a661ca2b44b 100644 --- a/ext/intl/locale/locale_class.h +++ b/ext/intl/locale/locale_class.h @@ -31,7 +31,7 @@ typedef struct { } Locale_object; -void locale_register_Locale_class( void ); +U_CFUNC void locale_register_Locale_class( void ); extern zend_class_entry *Locale_ce_ptr; diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.cpp similarity index 92% rename from ext/intl/locale/locale_methods.c rename to ext/intl/locale/locale_methods.cpp index 8b63007c5d820..fd8712b3b462a 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.cpp @@ -21,6 +21,7 @@ #include #include +extern "C" { #include "php_intl.h" #include "locale.h" #include "locale_class.h" @@ -32,6 +33,7 @@ #include #include "main/php_ini.h" #include "zend_smart_str.h" +} ZEND_EXTERN_MODULE_GLOBALS( intl ) @@ -296,7 +298,7 @@ static zend_off_t getSingletonPos(const char* str) /* {{{ Get default locale */ /* }}} */ /* {{{ Get default locale */ -PHP_NAMED_FUNCTION(zif_locale_get_default) +U_CFUNC PHP_NAMED_FUNCTION(zif_locale_get_default) { ZEND_PARSE_PARAMETERS_NONE(); @@ -308,7 +310,7 @@ PHP_NAMED_FUNCTION(zif_locale_get_default) /* {{{ Set default locale */ /* }}} */ /* {{{ Set default locale */ -PHP_NAMED_FUNCTION(zif_locale_set_default) +U_CFUNC PHP_NAMED_FUNCTION(zif_locale_set_default) { zend_string* locale_name; zend_string *ini_name; @@ -471,7 +473,6 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) size_t loc_name_len = 0; zend_string* tag_value = NULL; - char* empty_result = ""; int result = 0; char* msg = NULL; @@ -499,19 +500,18 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) if( tag_value){ zend_string_release_ex( tag_value, 0 ); } - RETURN_STRING( empty_result); + RETURN_EMPTY_STRING(); } /* value found */ if( tag_value){ - RETVAL_STR( tag_value ); - return; + RETURN_STR( tag_value ); } /* Error encountered while fetching the value */ if( result ==0) { - spprintf(&msg , 0, "locale_get_%s : unable to get locale %s", tag_name , tag_name ); - intl_error_set( NULL, status, msg , 1 ); + spprintf(&msg , 0, "unable to get locale %s", tag_name ); + intl_error_set( NULL, status, msg); efree(msg); RETURN_NULL(); } @@ -520,21 +520,21 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) /* }}} */ /* {{{ gets the script for the $locale */ -PHP_FUNCTION( locale_get_script ) +U_CFUNC PHP_FUNCTION( locale_get_script ) { get_icu_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the region for the $locale */ -PHP_FUNCTION( locale_get_region ) +U_CFUNC PHP_FUNCTION( locale_get_region ) { get_icu_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the primary language for the $locale */ -PHP_FUNCTION(locale_get_primary_language ) +U_CFUNC PHP_FUNCTION(locale_get_primary_language ) { get_icu_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -575,9 +575,7 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME if(loc_name_len > ULOC_FULLNAME_CAPACITY) { /* See bug 67397: overlong locale names cause trouble in uloc_getDisplayName */ - spprintf(&msg , 0, "locale_get_display_%s : name too long", tag_name ); - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, msg , 1 ); - efree(msg); + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "name too long"); RETURN_FALSE; } @@ -610,7 +608,7 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME /* Get the disp_value for the given locale */ do{ - disp_name = erealloc( disp_name , buflen * sizeof(UChar) ); + disp_name = reinterpret_cast(erealloc( disp_name , buflen * sizeof(UChar) )); disp_name_len = buflen; if( strcmp(tag_name , LOC_LANG_TAG)==0 ){ @@ -634,8 +632,8 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME continue; } - spprintf(&msg, 0, "locale_get_display_%s : unable to get locale %s", tag_name , tag_name ); - intl_error_set( NULL, status, msg , 1 ); + spprintf(&msg, 0, "unable to get locale %s", tag_name ); + intl_error_set( NULL, status, msg); efree(msg); if( disp_name){ efree( disp_name ); @@ -663,8 +661,8 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME efree( disp_name ); if( !u8str ) { - spprintf(&msg, 0, "locale_get_display_%s :error converting display name for %s to UTF-8", tag_name , tag_name ); - intl_error_set( NULL, status, msg , 1 ); + spprintf(&msg, 0, "error converting display name for %s to UTF-8", tag_name ); + intl_error_set( NULL, status, msg); efree(msg); RETURN_FALSE; } @@ -674,28 +672,28 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME /* }}} */ /* {{{ gets the name for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_name) +U_CFUNC PHP_FUNCTION(locale_get_display_name) { get_icu_disp_value_src_php( DISP_NAME , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the language for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_language) +U_CFUNC PHP_FUNCTION(locale_get_display_language) { get_icu_disp_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the script for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_script) +U_CFUNC PHP_FUNCTION(locale_get_display_script) { get_icu_disp_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } /* }}} */ /* {{{ gets the region for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_region) +U_CFUNC PHP_FUNCTION(locale_get_display_region) { get_icu_disp_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -709,7 +707,7 @@ PHP_FUNCTION(locale_get_display_region) * proto static string get_display_variant($locale, $in_locale = null) * gets the variant for the $locale in $in_locale or default_locale */ -PHP_FUNCTION(locale_get_display_variant) +U_CFUNC PHP_FUNCTION(locale_get_display_variant) { get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -721,7 +719,7 @@ PHP_FUNCTION(locale_get_display_variant) /* {{{ return an associative array containing keyword-value * pairs for this locale. The keys are keys to the array (doh!) */ -PHP_FUNCTION( locale_get_keywords ) +U_CFUNC PHP_FUNCTION( locale_get_keywords ) { UEnumeration* e = NULL; UErrorCode status = U_ZERO_ERROR; @@ -771,7 +769,7 @@ PHP_FUNCTION( locale_get_keywords ) kw_value_str = zend_string_truncate(kw_value_str, kw_value_len, 0); } if (U_FAILURE(status)) { - intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "locale_get_keywords: Error encountered while getting the keyword value for the keyword", 0 ); + intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "Error encountered while getting the keyword value for the keyword"); if( kw_value_str){ zend_string_efree( kw_value_str ); } @@ -791,7 +789,7 @@ PHP_FUNCTION( locale_get_keywords ) /* {{{ @return string the canonicalized locale * }}} */ /* {{{ @param string $locale The locale string to canonicalize */ -PHP_FUNCTION(locale_canonicalize) +U_CFUNC PHP_FUNCTION(locale_canonicalize) { get_icu_value_src_php( LOC_CANONICALIZE_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU ); } @@ -923,7 +921,7 @@ static int handleAppendResult( int result, smart_str* loc_name) intl_error_reset( NULL ); if( result == FAILURE) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, - "locale_compose: parameter array element is not a string", 0 ); + "parameter array element is not a string"); smart_str_free(loc_name); return 0; } @@ -936,9 +934,9 @@ static int handleAppendResult( int result, smart_str* loc_name) * }}} */ /* {{{ Creates a locale by combining the parts of locale-ID passed * }}} */ -PHP_FUNCTION(locale_compose) +U_CFUNC PHP_FUNCTION(locale_compose) { - smart_str loc_name_s = {0}; + smart_str loc_name_s = {NULL, 0}; smart_str *loc_name = &loc_name_s; zval* arr = NULL; HashTable* hash_arr = NULL; @@ -1083,7 +1081,7 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) } /* Over-allocates a few bytes for the integer so we don't have to reallocate. */ size_t cur_key_name_size = (sizeof("-2147483648") - 1) + strlen(key_name) + 1; - cur_key_name = emalloc(cur_key_name_size); + cur_key_name = reinterpret_cast(emalloc(cur_key_name_size)); snprintf( cur_key_name, cur_key_name_size , "%s%d", key_name , cnt++); add_assoc_string( hash_arr, cur_key_name , token); /* tokenize on the "_" or "-" and stop at singleton if any */ @@ -1117,7 +1115,7 @@ static int add_array_entry(const char* loc_name, zval* hash_arr, char* key_name) /* }}} */ /* {{{ parses a locale-id into an array the different parts of it */ -PHP_FUNCTION(locale_parse) +U_CFUNC PHP_FUNCTION(locale_parse) { char* loc_name = NULL; size_t loc_name_len = 0; @@ -1153,7 +1151,7 @@ PHP_FUNCTION(locale_parse) /* }}} */ /* {{{ gets an array containing the list of variants, or null */ -PHP_FUNCTION(locale_get_all_variants) +U_CFUNC PHP_FUNCTION(locale_get_all_variants) { char* loc_name = NULL; size_t loc_name_len = 0; @@ -1237,7 +1235,7 @@ static int strToMatch(const char* str ,char *retstr) /* {{{ Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm */ /* }}} */ /* {{{ Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm */ -PHP_FUNCTION(locale_filter_matches) +U_CFUNC PHP_FUNCTION(locale_filter_matches) { char* lang_tag = NULL; size_t lang_tag_len = 0; @@ -1282,21 +1280,19 @@ PHP_FUNCTION(locale_filter_matches) /* canonicalize loc_range */ can_loc_range=get_icu_value_internal( loc_range , LOC_CANONICALIZE_TAG , &result , 0); if( result <=0) { - intl_error_set( NULL, status, - "locale_filter_matches : unable to canonicalize loc_range" , 0 ); + intl_error_set(NULL, status, "unable to canonicalize loc_range"); RETURN_FALSE; } /* canonicalize lang_tag */ can_lang_tag = get_icu_value_internal( lang_tag , LOC_CANONICALIZE_TAG , &result , 0); if( result <=0) { - intl_error_set( NULL, status, - "locale_filter_matches : unable to canonicalize lang_tag" , 0 ); + intl_error_set(NULL, status, "unable to canonicalize lang_tag"); RETURN_FALSE; } /* Convert to lower case for case-insensitive comparison */ - cur_lang_tag = ecalloc( 1, can_lang_tag->len + 1); + cur_lang_tag = reinterpret_cast(ecalloc( 1, can_lang_tag->len + 1)); /* Convert to lower case for case-insensitive comparison */ result = strToMatch( can_lang_tag->val , cur_lang_tag); @@ -1306,7 +1302,7 @@ PHP_FUNCTION(locale_filter_matches) RETURN_FALSE; } - cur_loc_range = ecalloc( 1, can_loc_range->len + 1); + cur_loc_range = reinterpret_cast(ecalloc( 1, can_loc_range->len + 1)); result = strToMatch( can_loc_range->val , cur_loc_range ); if( result == 0) { efree( cur_lang_tag ); @@ -1353,14 +1349,14 @@ PHP_FUNCTION(locale_filter_matches) } /* end of if isCanonical */ else{ /* Convert to lower case for case-insensitive comparison */ - cur_lang_tag = ecalloc( 1, strlen(lang_tag ) + 1); + cur_lang_tag = reinterpret_cast(ecalloc( 1, strlen(lang_tag ) + 1)); result = strToMatch( lang_tag , cur_lang_tag); if( result == 0) { efree( cur_lang_tag ); RETURN_FALSE; } - cur_loc_range = ecalloc( 1, strlen(loc_range ) + 1); + cur_loc_range = reinterpret_cast(ecalloc( 1, strlen(loc_range ) + 1)); result = strToMatch( loc_range , cur_loc_range ); if( result == 0) { efree( cur_lang_tag ); @@ -1425,7 +1421,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, zend_string* return_value = NULL; - char **cur_arr = ecalloc(zend_hash_num_elements(hash_arr)*2, sizeof(char *)); + char **cur_arr = reinterpret_cast(ecalloc(zend_hash_num_elements(hash_arr)*2, sizeof(char *))); ZEND_HASH_FOREACH_VAL(hash_arr, ele_value) { ZVAL_DEREF(ele_value); /* convert the array to lowercase , also replace hyphens with the underscore and store it in cur_arr */ @@ -1441,7 +1437,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_P(ele_value), Z_STRLEN_P(ele_value)); result = strToMatch(Z_STRVAL_P(ele_value), cur_arr[cur_arr_len*2]); if(result == 0) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag", 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "unable to canonicalize lang_tag"); LOOKUP_CLEAN_RETURN(NULL); } cur_arr[cur_arr_len*2+1] = Z_STRVAL_P(ele_value); @@ -1456,14 +1452,14 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, if(lang_tag) { zend_string_release_ex(lang_tag, 0); } - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "unable to canonicalize lang_tag"); LOOKUP_CLEAN_RETURN(NULL); } - cur_arr[i*2] = erealloc(cur_arr[i*2], lang_tag->len+1); + cur_arr[i*2] = reinterpret_cast(erealloc(cur_arr[i*2], lang_tag->len+1)); result = strToMatch(lang_tag->val, cur_arr[i*2]); zend_string_release_ex(lang_tag, 0); if(result == 0) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "unable to canonicalize lang_tag"); LOOKUP_CLEAN_RETURN(NULL); } } @@ -1475,7 +1471,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, can_loc_range = get_icu_value_internal(loc_range, LOC_CANONICALIZE_TAG, &result , 0); if( result != 1 || can_loc_range == NULL || !can_loc_range->val[0]) { /* Error */ - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize loc_range" , 0 ); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "unable to canonicalize loc_range"); if(can_loc_range) { zend_string_release_ex(can_loc_range, 0); } @@ -1485,7 +1481,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, } } - cur_loc_range = ecalloc(1, strlen(loc_range)+1); + cur_loc_range = reinterpret_cast(ecalloc(1, strlen(loc_range)+1)); /* convert to lower and replace hyphens */ result = strToMatch(loc_range, cur_loc_range); if(can_loc_range) { @@ -1493,7 +1489,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, } if(result == 0) { efree(cur_loc_range); - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "unable to canonicalize lang_tag"); LOOKUP_CLEAN_RETURN(NULL); } @@ -1525,7 +1521,7 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, /* {{{ Searches the items in $langtag for the best match to the language * range */ -PHP_FUNCTION(locale_lookup) +U_CFUNC PHP_FUNCTION(locale_lookup) { zend_string* fallback_loc_str = NULL; char* loc_range = NULL; @@ -1580,12 +1576,12 @@ PHP_FUNCTION(locale_lookup) /* {{{ Tries to find out best available locale based on HTTP "Accept-Language" header */ /* }}} */ /* {{{ Tries to find out best available locale based on HTTP "Accept-Language" header */ -PHP_FUNCTION(locale_accept_from_http) +U_CFUNC PHP_FUNCTION(locale_accept_from_http) { UEnumeration *available; char *http_accept = NULL; size_t http_accept_len; - UErrorCode status = 0; + UErrorCode status = U_ZERO_ERROR; int len; char resultLocale[INTL_MAX_LOCALE_LEN+1]; UAcceptResult outResult; @@ -1603,7 +1599,7 @@ PHP_FUNCTION(locale_accept_from_http) len = end ? end-start : http_accept_len-(start-http_accept); if(len > ULOC_FULLNAME_CAPACITY) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, - "locale_accept_from_http: locale string too long", 0 ); + "locale string too long"); RETURN_FALSE; } if(end) { @@ -1613,11 +1609,11 @@ PHP_FUNCTION(locale_accept_from_http) } available = ures_openAvailableLocales(NULL, &status); - INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list"); + INTL_CHECK_STATUS(status, "failed to retrieve locale list"); len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN, &outResult, http_accept, available, &status); uenum_close(available); - INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to find acceptable locale"); + INTL_CHECK_STATUS(status, "failed to find acceptable locale"); if (len < 0 || outResult == ULOC_ACCEPT_FAILED) { RETURN_FALSE; } @@ -1625,7 +1621,7 @@ PHP_FUNCTION(locale_accept_from_http) } /* }}} */ -PHP_FUNCTION(locale_is_right_to_left) +U_CFUNC PHP_FUNCTION(locale_is_right_to_left) { char *locale; size_t locale_len; @@ -1641,10 +1637,10 @@ PHP_FUNCTION(locale_is_right_to_left) RETURN_BOOL(uloc_isRightToLeft(locale)); } -PHP_FUNCTION(locale_add_likely_subtags) +U_CFUNC PHP_FUNCTION(locale_add_likely_subtags) { char *locale, maximized_locale[ULOC_FULLNAME_CAPACITY]; - UErrorCode status = 0; + UErrorCode status = U_ZERO_ERROR; size_t locale_len; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -1656,7 +1652,7 @@ PHP_FUNCTION(locale_add_likely_subtags) } int32_t maximized_locale_len = uloc_addLikelySubtags(locale, maximized_locale, sizeof(maximized_locale), &status); - INTL_CHECK_STATUS(status, "locale_add_likely_subtags: invalid locale"); + INTL_CHECK_STATUS(status, "invalid locale"); if (maximized_locale_len < 0) { RETURN_FALSE; } @@ -1664,10 +1660,10 @@ PHP_FUNCTION(locale_add_likely_subtags) RETURN_STRINGL(maximized_locale, maximized_locale_len); } -PHP_FUNCTION(locale_minimize_subtags) +U_CFUNC PHP_FUNCTION(locale_minimize_subtags) { char *locale, minimized_locale[ULOC_FULLNAME_CAPACITY]; - UErrorCode status = 0; + UErrorCode status = U_ZERO_ERROR; size_t locale_len; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -1679,7 +1675,7 @@ PHP_FUNCTION(locale_minimize_subtags) } int32_t minimized_locale_len = uloc_minimizeSubtags(locale, minimized_locale, sizeof(minimized_locale), &status); - INTL_CHECK_STATUS(status, "locale_minimize_subtags: invalid locale"); + INTL_CHECK_STATUS(status, "invalid locale"); if (minimized_locale_len < 0) { RETURN_FALSE; } diff --git a/ext/intl/msgformat/msgformat.c b/ext/intl/msgformat/msgformat.cpp similarity index 77% rename from ext/intl/msgformat/msgformat.c rename to ext/intl/msgformat/msgformat.cpp index 51643d86d458a..a9e1f71bfc60a 100644 --- a/ext/intl/msgformat/msgformat.c +++ b/ext/intl/msgformat/msgformat.cpp @@ -19,13 +19,15 @@ #include #include +extern "C" { #include "php_intl.h" #include "msgformat_class.h" #include "msgformat_data.h" #include "intl_convert.h" +} /* {{{ */ -static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) +static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS) { char* locale; char* pattern; @@ -43,18 +45,13 @@ static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_ Z_PARAM_STRING(pattern, pattern_len) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); - if (error_handling != NULL) { - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; - } - INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); MSG_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; /* Convert pattern (if specified) to UTF-16. */ if(pattern && pattern_len) { intl_convert_utf8_to_utf16(&spattern, &spattern_len, pattern, pattern_len, &INTL_DATA_ERROR_CODE(mfo)); - INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: error converting pattern to UTF-16"); + INTL_CTOR_CHECK_STATUS(mfo, "error converting pattern to UTF-16"); } else { spattern_len = 0; spattern = NULL; @@ -92,22 +89,22 @@ static int msgfmt_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_ smart_str_free( &parse_error_str ); intl_error_set_code( NULL, INTL_DATA_ERROR_CODE( mfo ) ); - intl_errors_set_custom_msg( INTL_DATA_ERROR_P( mfo ), msg, 1 ); + intl_errors_set_custom_msg( INTL_DATA_ERROR_P( mfo ), msg); efree( msg ); return FAILURE; } - INTL_CTOR_CHECK_STATUS(mfo, "msgfmt_create: message formatter creation failed"); + INTL_CTOR_CHECK_STATUS(mfo, "message formatter creation failed"); return SUCCESS; } /* }}} */ /* {{{ Create formatter. */ -PHP_FUNCTION( msgfmt_create ) +U_CFUNC PHP_FUNCTION( msgfmt_create ) { object_init_ex( return_value, MessageFormatter_ce_ptr ); - if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { + if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { zval_ptr_dtor(return_value); RETURN_NULL(); } @@ -115,27 +112,24 @@ PHP_FUNCTION( msgfmt_create ) /* }}} */ /* {{{ MessageFormatter object constructor. */ -PHP_METHOD( MessageFormatter, __construct ) +U_CFUNC PHP_METHOD( MessageFormatter, __construct ) { - zend_error_handling error_handling; - bool error_handling_replaced = 0; + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; return_value = ZEND_THIS; - if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) { - if (!EG(exception)) { - zend_string *err = intl_error_get_message(NULL); - zend_throw_exception(IntlException_ce_ptr, ZSTR_VAL(err), intl_error_get_code(NULL)); - zend_string_release_ex(err, 0); - } - } - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); + if (msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + ZEND_ASSERT(EG(exception)); } + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } /* }}} */ /* {{{ Get formatter's last error code. */ -PHP_FUNCTION( msgfmt_get_error_code ) +U_CFUNC PHP_FUNCTION( msgfmt_get_error_code ) { zval* object = NULL; MessageFormatter_object* mfo = NULL; @@ -155,7 +149,7 @@ PHP_FUNCTION( msgfmt_get_error_code ) /* }}} */ /* {{{ Get text description for formatter's last error code. */ -PHP_FUNCTION( msgfmt_get_error_message ) +U_CFUNC PHP_FUNCTION( msgfmt_get_error_message ) { zend_string* message = NULL; zval* object = NULL; diff --git a/ext/intl/msgformat/msgformat_attr.c b/ext/intl/msgformat/msgformat_attr.cpp similarity index 94% rename from ext/intl/msgformat/msgformat_attr.c rename to ext/intl/msgformat/msgformat_attr.cpp index b56bf360d114d..e7ec006e5e793 100644 --- a/ext/intl/msgformat/msgformat_attr.c +++ b/ext/intl/msgformat/msgformat_attr.cpp @@ -16,15 +16,17 @@ #include #endif +extern "C" { #include "php_intl.h" #include "msgformat_class.h" #include "msgformat_data.h" #include "intl_convert.h" +} #include /* {{{ Get formatter pattern. */ -PHP_FUNCTION( msgfmt_get_pattern ) +U_CFUNC PHP_FUNCTION( msgfmt_get_pattern ) { MSG_FORMAT_METHOD_INIT_VARS; @@ -46,7 +48,7 @@ PHP_FUNCTION( msgfmt_get_pattern ) /* }}} */ /* {{{ Set formatter pattern. */ -PHP_FUNCTION( msgfmt_set_pattern ) +U_CFUNC PHP_FUNCTION( msgfmt_set_pattern ) { char* value = NULL; size_t value_len = 0; @@ -83,7 +85,7 @@ PHP_FUNCTION( msgfmt_set_pattern ) if (U_FAILURE(INTL_DATA_ERROR_CODE(mfo))) { char *msg; spprintf(&msg, 0, "Error setting symbol value at line %d, offset %d", spattern_error.line, spattern_error.offset); - intl_errors_set_custom_msg(INTL_DATA_ERROR_P(mfo), msg, 1); + intl_errors_set_custom_msg(INTL_DATA_ERROR_P(mfo), msg); efree(msg); RETURN_FALSE; } @@ -105,7 +107,7 @@ PHP_FUNCTION( msgfmt_set_pattern ) /* }}} */ /* {{{ Get formatter locale. */ -PHP_FUNCTION( msgfmt_get_locale ) +U_CFUNC PHP_FUNCTION( msgfmt_get_locale ) { char *loc; MSG_FORMAT_METHOD_INIT_VARS; diff --git a/ext/intl/msgformat/msgformat_class.c b/ext/intl/msgformat/msgformat_class.cpp similarity index 87% rename from ext/intl/msgformat/msgformat_class.c rename to ext/intl/msgformat/msgformat_class.cpp index 4e0766a911b9a..e762febf0d1b3 100644 --- a/ext/intl/msgformat/msgformat_class.c +++ b/ext/intl/msgformat/msgformat_class.cpp @@ -14,10 +14,12 @@ #include +extern "C" { #include "msgformat_class.h" #include "php_intl.h" #include "msgformat_data.h" #include "msgformat_arginfo.h" +} #include @@ -29,7 +31,7 @@ static zend_object_handlers MessageFormatter_handlers; */ /* {{{ MessageFormatter_objects_free */ -void MessageFormatter_object_free( zend_object *object ) +U_CFUNC void MessageFormatter_object_free( zend_object *object ) { MessageFormatter_object* mfo = php_intl_messageformatter_fetch_object(object); @@ -40,11 +42,11 @@ void MessageFormatter_object_free( zend_object *object ) /* }}} */ /* {{{ MessageFormatter_object_create */ -zend_object *MessageFormatter_object_create(zend_class_entry *ce) +U_CFUNC zend_object *MessageFormatter_object_create(zend_class_entry *ce) { MessageFormatter_object* intern; - intern = zend_object_alloc(sizeof(MessageFormatter_object), ce); + intern = reinterpret_cast(zend_object_alloc(sizeof(MessageFormatter_object), ce)); msgformat_data_init( &intern->mf_data ); zend_object_std_init( &intern->zo, ce ); object_properties_init(&intern->zo, ce); @@ -54,7 +56,7 @@ zend_object *MessageFormatter_object_create(zend_class_entry *ce) /* }}} */ /* {{{ MessageFormatter_object_clone */ -zend_object *MessageFormatter_object_clone(zend_object *object) +U_CFUNC zend_object *MessageFormatter_object_clone(zend_object *object) { MessageFormatter_object *mfo = php_intl_messageformatter_fetch_object(object); zend_object *new_obj = MessageFormatter_ce_ptr->create_object(object->ce); @@ -66,7 +68,7 @@ zend_object *MessageFormatter_object_clone(zend_object *object) /* clone formatter object */ if (MSG_FORMAT_OBJECT(mfo) != NULL) { UErrorCode error = U_ZERO_ERROR; - MSG_FORMAT_OBJECT(new_mfo) = umsg_clone(MSG_FORMAT_OBJECT(mfo), &error); + MSG_FORMAT_OBJECT(new_mfo) = reinterpret_cast(umsg_clone(MSG_FORMAT_OBJECT(mfo), &error)); if (U_FAILURE(error)) { zend_throw_error(NULL, "Failed to clone MessageFormatter"); diff --git a/ext/intl/msgformat/msgformat_data.c b/ext/intl/msgformat/msgformat_data.cpp similarity index 92% rename from ext/intl/msgformat/msgformat_data.c rename to ext/intl/msgformat/msgformat_data.cpp index 5d170d25945fa..f8b7ec39601eb 100644 --- a/ext/intl/msgformat/msgformat_data.c +++ b/ext/intl/msgformat/msgformat_data.cpp @@ -24,7 +24,7 @@ /* {{{ void msgformat_data_init( msgformat_data* mf_data ) * Initialize internals of msgformat_data. */ -void msgformat_data_init( msgformat_data* mf_data ) +U_CFUNC void msgformat_data_init( msgformat_data* mf_data ) { if( !mf_data ) return; @@ -40,7 +40,7 @@ void msgformat_data_init( msgformat_data* mf_data ) /* {{{ void msgformat_data_free( msgformat_data* mf_data ) * Clean up memory allocated for msgformat_data */ -void msgformat_data_free(msgformat_data* mf_data) +U_CFUNC void msgformat_data_free(msgformat_data* mf_data) { if (!mf_data) return; @@ -69,7 +69,7 @@ void msgformat_data_free(msgformat_data* mf_data) */ msgformat_data* msgformat_data_create( void ) { - msgformat_data* mf_data = ecalloc( 1, sizeof(msgformat_data) ); + msgformat_data* mf_data = reinterpret_cast(ecalloc( 1, sizeof(msgformat_data) )); msgformat_data_init( mf_data ); diff --git a/ext/intl/msgformat/msgformat_data.h b/ext/intl/msgformat/msgformat_data.h index 539c7d6d92557..bac94cbec34c3 100644 --- a/ext/intl/msgformat/msgformat_data.h +++ b/ext/intl/msgformat/msgformat_data.h @@ -17,7 +17,13 @@ #include +#ifdef __cplusplus +extern "C" { +#endif #include "../intl_error.h" +#ifdef __cplusplus +} +#endif #include @@ -26,16 +32,22 @@ typedef struct { intl_error error; // formatter handling - UMessageFormat* umsgf; + UMessageFormat *umsgf; char* orig_format; zend_ulong orig_format_len; HashTable* arg_types; int tz_set; /* if we've already the time zone in sub-formats */ } msgformat_data; +#ifdef __cplusplus +extern "C" { +#endif msgformat_data* msgformat_data_create( void ); void msgformat_data_init( msgformat_data* mf_data ); void msgformat_data_free( msgformat_data* mf_data ); +#ifdef __cplusplus +} +#endif #ifdef MSG_FORMAT_QUOTE_APOS int msgformat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec); diff --git a/ext/intl/msgformat/msgformat_format.c b/ext/intl/msgformat/msgformat_format.cpp similarity index 94% rename from ext/intl/msgformat/msgformat_format.c rename to ext/intl/msgformat/msgformat_format.cpp index 46a364c5d3a21..8e3ec28b389e1 100644 --- a/ext/intl/msgformat/msgformat_format.c +++ b/ext/intl/msgformat/msgformat_format.cpp @@ -18,11 +18,13 @@ #include +extern "C" { #include "php_intl.h" #include "msgformat_class.h" #include "msgformat_data.h" #include "msgformat_helpers.h" #include "intl_convert.h" +} #ifndef Z_ADDREF_P #define Z_ADDREF_P(z) ((z)->refcount++) @@ -48,7 +50,7 @@ static void msgfmt_do_format(MessageFormatter_object *mfo, zval *args, zval *ret /* }}} */ /* {{{ Format a message. */ -PHP_FUNCTION( msgfmt_format ) +U_CFUNC PHP_FUNCTION( msgfmt_format ) { zval *args; MSG_FORMAT_METHOD_INIT_VARS; @@ -69,7 +71,7 @@ PHP_FUNCTION( msgfmt_format ) /* }}} */ /* {{{ Format a message. */ -PHP_FUNCTION( msgfmt_format_message ) +U_CFUNC PHP_FUNCTION( msgfmt_format_message ) { zval *args; UChar *spattern = NULL; @@ -99,7 +101,7 @@ PHP_FUNCTION( msgfmt_format_message ) if( U_FAILURE(INTL_DATA_ERROR_CODE((mfo))) ) { intl_error_set(/* intl_error* */ NULL, U_ILLEGAL_ARGUMENT_ERROR, - "msgfmt_format_message: error converting pattern to UTF-16", 0 ); + "error converting pattern to UTF-16"); RETURN_FALSE; } } else { @@ -114,7 +116,7 @@ PHP_FUNCTION( msgfmt_format_message ) #ifdef MSG_FORMAT_QUOTE_APOS if(msgformat_fix_quotes(&spattern, &spattern_len, &INTL_DATA_ERROR_CODE(mfo)) != SUCCESS) { intl_error_set(/* intl_error* */ NULL, U_INVALID_FORMAT_ERROR, - "msgfmt_format_message: error converting pattern to quote-friendly format", 0 ); + "msgfmt_format_message: error converting pattern to quote-friendly format"); RETURN_FALSE; } #endif @@ -136,11 +138,11 @@ PHP_FUNCTION( msgfmt_format_message ) /* Pass NULL to intl_error* parameter to store message in global Intl error msg stack */ intl_error_set_code(/* intl_error* */ NULL, INTL_DATA_ERROR_CODE( mfo ) ); - intl_errors_set_custom_msg(/* intl_error* */ NULL, msg, 1 ); + intl_errors_set_custom_msg(/* intl_error* */ NULL, msg); efree( msg ); } else { - intl_errors_set_custom_msg(/* intl_error* */ NULL, "Creating message formatter failed", 0 ); + intl_errors_set_custom_msg(/* intl_error* */ NULL, "Creating message formatter failed"); } umsg_close(MSG_FORMAT_OBJECT(mfo)); RETURN_FALSE; diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index fbd85b857f3bc..e734b2df27b84 100644 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -187,7 +187,7 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, int32_t argNumber = name_part.getValue(); if (argNumber < 0) { intl_errors_set(&err, U_INVALID_FORMAT_ERROR, - "Found part with negative number", 0); + "Found part with negative number"); continue; } if ((storedType = (Formattable::Type*)zend_hash_index_find_ptr(ret, (zend_ulong)argNumber)) == NULL) { @@ -196,7 +196,7 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, storedType = (Formattable::Type*)zend_hash_index_update_mem(ret, (zend_ulong)argNumber, (void*)&bogusType, sizeof(bogusType)); } } else { - intl_errors_set(&err, U_INVALID_FORMAT_ERROR, "Invalid part type encountered", 0); + intl_errors_set(&err, U_INVALID_FORMAT_ERROR, "Invalid part type encountered"); continue; } @@ -243,7 +243,7 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, * is broken. */ intl_errors_set(&err, U_PARSE_ERROR, "Expected UMSGPAT_PART_TYPE_ARG_TYPE part following " - "UMSGPAT_ARG_TYPE_SIMPLE part", 0); + "UMSGPAT_ARG_TYPE_SIMPLE part"); continue; } } else if (argType == UMSGPAT_ARG_TYPE_PLURAL) { @@ -262,7 +262,7 @@ static HashTable *umsg_parse_format(MessageFormatter_object *mfo, /* We found a different type for the same arg! */ if (*storedType != Formattable::kObject && *storedType != type) { intl_errors_set(&err, U_ARGUMENT_TYPE_MISMATCH, - "Inconsistent types declared for an argument", 0); + "Inconsistent types declared for an argument"); continue; } @@ -330,7 +330,7 @@ static void umsg_set_timezone(MessageFormatter_object *mfo, if (UNEXPECTED(formats == NULL)) { intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR, - "Out of memory retrieving subformats", 0); + "Out of memory retrieving subformats"); } for (int i = 0; U_SUCCESS(err.code) && i < count; i++) { @@ -341,9 +341,7 @@ static void umsg_set_timezone(MessageFormatter_object *mfo, } if (used_tz == NULL) { - zval nullzv; - ZVAL_NULL(&nullzv); - used_tz = timezone_process_timezone_argument(&nullzv, &err, "msgfmt_format"); + used_tz = timezone_process_timezone_argument(nullptr, nullptr, &err); if (used_tz == NULL) { continue; } @@ -405,7 +403,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, /* includes case where index < 0 because it's exposed as unsigned */ if (UNEXPECTED(num_index > (zend_ulong)INT32_MAX)) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, - "Found negative or too large array key", 0); + "Found negative or too large array key"); continue; } @@ -421,7 +419,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, char *message; spprintf(&message, 0, "Invalid UTF-8 data in argument key: '%s'", ZSTR_VAL(str_index)); - intl_errors_set(&err, err.code, message, 1); + intl_errors_set(&err, err.code, message); efree(message); continue; } @@ -457,7 +455,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, char *message; spprintf(&message, 0, "Invalid UTF-8 data in string argument: " "'%s'", ZSTR_VAL(str)); - intl_errors_set(&err, err.code, message, 1); + intl_errors_set(&err, err.code, message); efree(message); delete text; continue; @@ -481,7 +479,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, Z_DVAL_P(elem) < (double)INT32_MIN)) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " - "32 bit integer argument", 0); + "32 bit integer argument"); } else { tInt32 = (int32_t)Z_DVAL_P(elem); } @@ -490,7 +488,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, Z_LVAL_P(elem) < INT32_MIN)) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP integer with absolute value too large " - "for 32 bit integer argument", 0); + "for 32 bit integer argument"); } else { tInt32 = (int32_t)Z_LVAL_P(elem); } @@ -509,7 +507,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, Z_DVAL_P(elem) < (double)U_INT64_MIN)) { intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, "Found PHP float with absolute value too large for " - "64 bit integer argument", 0); + "64 bit integer argument"); } else { tInt64 = (int64_t)Z_DVAL_P(elem); } @@ -524,7 +522,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, } case Formattable::kDate: { - double dd = intl_zval_to_millis(elem, &err, "msgfmt_format"); + double dd = intl_zval_to_millis(elem, &err); if (U_FAILURE(err.code)) { char *message; zend_string *u8key; @@ -533,7 +531,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, if (u8key) { spprintf(&message, 0, "The argument for key '%s' " "cannot be used as a date or time", ZSTR_VAL(u8key)); - intl_errors_set(&err, err.code, message, 1); + intl_errors_set(&err, err.code, message); zend_string_release_ex(u8key, 0); efree(message); } @@ -544,7 +542,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, } default: intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, - "Found unsupported argument type", 0); + "Found unsupported argument type"); break; } } else { @@ -578,8 +576,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, spprintf(&message, 0, "No strategy to convert the " "value given for the argument with key '%s' " "is available", ZSTR_VAL(u8key)); - intl_errors_set(&err, - U_ILLEGAL_ARGUMENT_ERROR, message, 1); + intl_errors_set(&err, U_ILLEGAL_ARGUMENT_ERROR, message); zend_string_release_ex(u8key, 0); efree(message); } @@ -602,7 +599,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, if (U_FAILURE(err.code)) { intl_errors_set(&err, err.code, - "Call to ICU MessageFormat::format() has failed", 0); + "Call to ICU MessageFormat::format() has failed"); return; } @@ -610,8 +607,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, *formatted = eumalloc(*formatted_len+1); resultStr.extract(*formatted, *formatted_len+1, err.code); if (U_FAILURE(err.code)) { - intl_errors_set(&err, err.code, - "Error copying format() result", 0); + intl_errors_set(&err, err.code, "Error copying format() result"); return; } } diff --git a/ext/intl/msgformat/msgformat_parse.c b/ext/intl/msgformat/msgformat_parse.cpp similarity index 94% rename from ext/intl/msgformat/msgformat_parse.c rename to ext/intl/msgformat/msgformat_parse.cpp index 80ede995c42e7..28d7ce7108021 100644 --- a/ext/intl/msgformat/msgformat_parse.c +++ b/ext/intl/msgformat/msgformat_parse.cpp @@ -18,11 +18,13 @@ #include +extern "C" { #include "php_intl.h" #include "msgformat_class.h" #include "msgformat_data.h" #include "msgformat_helpers.h" #include "intl_convert.h" +} /* {{{ */ static void msgfmt_do_parse(MessageFormatter_object *mfo, char *source, size_t src_len, zval *return_value) @@ -52,7 +54,7 @@ static void msgfmt_do_parse(MessageFormatter_object *mfo, char *source, size_t s /* }}} */ /* {{{ Parse a message */ -PHP_FUNCTION( msgfmt_parse ) +U_CFUNC PHP_FUNCTION( msgfmt_parse ) { char *source; size_t source_len; @@ -74,7 +76,7 @@ PHP_FUNCTION( msgfmt_parse ) /* }}} */ /* {{{ Parse a message. */ -PHP_FUNCTION( msgfmt_parse_message ) +U_CFUNC PHP_FUNCTION( msgfmt_parse_message ) { UChar *spattern = NULL; int spattern_len = 0; @@ -102,7 +104,7 @@ PHP_FUNCTION( msgfmt_parse_message ) if( U_FAILURE(INTL_DATA_ERROR_CODE((mfo))) ) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, - "msgfmt_parse_message: error converting pattern to UTF-16", 0 ); + "error converting pattern to UTF-16"); RETURN_FALSE; } } else { @@ -127,10 +129,11 @@ PHP_FUNCTION( msgfmt_parse_message ) if(spattern && spattern_len) { efree(spattern); } - INTL_METHOD_CHECK_STATUS(mfo, "Creating message formatter failed"); + INTL_METHOD_CHECK_STATUS_OR_GOTO(mfo, "Creating message formatter failed", clean); msgfmt_do_parse(mfo, source, src_len, return_value); +clean: /* drop the temporary formatter */ msgformat_data_free(&mfo->mf_data); } diff --git a/ext/intl/normalizer/normalizer_class.c b/ext/intl/normalizer/normalizer_class.cpp similarity index 86% rename from ext/intl/normalizer/normalizer_class.c rename to ext/intl/normalizer/normalizer_class.cpp index d9e413d5e5146..3838f7546325a 100644 --- a/ext/intl/normalizer/normalizer_class.c +++ b/ext/intl/normalizer/normalizer_class.cpp @@ -12,11 +12,22 @@ +----------------------------------------------------------------------+ */ +#if __cplusplus >= 201703L +#include +#endif +#include + #include "normalizer.h" #include "normalizer_class.h" #include "php_intl.h" +#ifdef __cplusplus +extern "C" { +#endif #include "normalizer_arginfo.h" #include "intl_error.h" +#ifdef __cplusplus +} +#endif #include @@ -29,7 +40,7 @@ zend_class_entry *Normalizer_ce_ptr = NULL; /* {{{ normalizer_register_Normalizer_class * Initialize 'Normalizer' class */ -void normalizer_register_Normalizer_class( void ) +U_CFUNC void normalizer_register_Normalizer_class( void ) { /* Create and register 'Normalizer' class. */ Normalizer_ce_ptr = register_class_Normalizer(); diff --git a/ext/intl/normalizer/normalizer_class.h b/ext/intl/normalizer/normalizer_class.h index 6e57cae40ba0e..8f88f215abcca 100644 --- a/ext/intl/normalizer/normalizer_class.h +++ b/ext/intl/normalizer/normalizer_class.h @@ -36,6 +36,12 @@ typedef struct { #define NORMALIZER_ERROR_CODE(co) INTL_ERROR_CODE(NORMALIZER_ERROR(co)) #define NORMALIZER_ERROR_CODE_P(co) &(INTL_ERROR_CODE(NORMALIZER_ERROR(co))) +#ifdef __cplusplus +extern "C" { +#endif void normalizer_register_Normalizer_class( void ); +#ifdef __cplusplus +} +#endif extern zend_class_entry *Normalizer_ce_ptr; #endif // #ifndef NORMALIZER_CLASS_H diff --git a/ext/intl/normalizer/normalizer_normalize.c b/ext/intl/normalizer/normalizer_normalize.cpp similarity index 93% rename from ext/intl/normalizer/normalizer_normalize.c rename to ext/intl/normalizer/normalizer_normalize.cpp index 38f12134146a5..92e8f1166ad00 100644 --- a/ext/intl/normalizer/normalizer_normalize.c +++ b/ext/intl/normalizer/normalizer_normalize.cpp @@ -16,11 +16,18 @@ #include #endif +#if __cplusplus >= 201703L +#include +#include +#endif + +extern "C" { #include "php_intl.h" #include #include "normalizer.h" #include "normalizer_class.h" #include "intl_convert.h" +} #include @@ -71,7 +78,7 @@ static UBool intl_is_normalized(zend_long form, const UChar *uinput, int32_t uin }/*}}}*/ /* {{{ Normalize a string. */ -PHP_FUNCTION( normalizer_normalize ) +U_CFUNC PHP_FUNCTION( normalizer_normalize ) { char* input = NULL; /* form is optional, defaults to FORM_C */ @@ -130,7 +137,7 @@ PHP_FUNCTION( normalizer_normalize ) intl_error_set_code( NULL, status ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16", 0 ); + intl_error_set_custom_msg( NULL, "Error converting input string to UTF-16"); if (uinput) { efree( uinput ); } @@ -150,7 +157,7 @@ PHP_FUNCTION( normalizer_normalize ) * (U_STRING_NOT_TERMINATED_WARNING usually means that the input string is empty). */ if( U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR && status != U_STRING_NOT_TERMINATED_WARNING ) { - intl_error_set_custom_msg( NULL, "Error normalizing string", 0 ); + intl_error_set_custom_msg( NULL, "Error normalizing string"); efree( uret_buf ); efree( uinput ); RETURN_FALSE; @@ -172,7 +179,7 @@ PHP_FUNCTION( normalizer_normalize ) /* Bail out if an unexpected error occurred. */ if( U_FAILURE(status) ) { /* Set error messages. */ - intl_error_set_custom_msg( NULL,"Error normalizing string", 0 ); + intl_error_set_custom_msg( NULL,"Error normalizing string"); efree( uret_buf ); efree( uinput ); RETURN_FALSE; @@ -190,7 +197,7 @@ PHP_FUNCTION( normalizer_normalize ) if( !u8str ) { intl_error_set( NULL, status, - "normalizer_normalize: error converting normalized text UTF-8", 0 ); + "error converting normalized text UTF-8"); RETURN_FALSE; } @@ -200,7 +207,7 @@ PHP_FUNCTION( normalizer_normalize ) /* }}} */ /* {{{ Test if a string is in a given normalization form. */ -PHP_FUNCTION( normalizer_is_normalized ) +U_CFUNC PHP_FUNCTION( normalizer_is_normalized ) { char* input = NULL; /* form is optional, defaults to FORM_C */ @@ -248,7 +255,7 @@ PHP_FUNCTION( normalizer_is_normalized ) intl_error_set_code( NULL, status ); /* Set error messages. */ - intl_error_set_custom_msg( NULL, "Error converting string to UTF-16.", 0 ); + intl_error_set_custom_msg( NULL, "Error converting string to UTF-16."); if (uinput) { efree( uinput ); } @@ -264,7 +271,7 @@ PHP_FUNCTION( normalizer_is_normalized ) /* Bail out if an unexpected error occurred. */ if( U_FAILURE(status) ) { /* Set error messages. */ - intl_error_set_custom_msg( NULL,"Error testing if string is the given normalization form.", 0 ); + intl_error_set_custom_msg( NULL,"Error testing if string is the given normalization form."); RETURN_FALSE; } @@ -276,7 +283,7 @@ PHP_FUNCTION( normalizer_is_normalized ) /* }}} */ /* {{{ Returns the Decomposition_Mapping property for the given UTF-8 encoded code point. */ -PHP_FUNCTION( normalizer_get_raw_decomposition ) +U_CFUNC PHP_FUNCTION( normalizer_get_raw_decomposition ) { char* input = NULL; size_t input_length = 0; @@ -304,13 +311,13 @@ PHP_FUNCTION( normalizer_get_raw_decomposition ) U8_NEXT(input, offset, input_length, codepoint); if ((size_t)offset != input_length) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Input string must be exactly one UTF-8 encoded code point long.", 0); + intl_error_set_custom_msg(NULL, "Input string must be exactly one UTF-8 encoded code point long."); return; } if ((codepoint < UCHAR_MIN_VALUE) || (codepoint > UCHAR_MAX_VALUE)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Code point out of range", 0); + intl_error_set_custom_msg(NULL, "Code point out of range"); return; } diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 68fd2dedfba85..9ede8a92e97a8 100644 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -98,10 +98,38 @@ const char *intl_locale_get_default( void ) return INTL_G(default_locale); } +char* canonicalize_locale_string(const char* locale) { + char canonicalized[ULOC_FULLNAME_CAPACITY]; + UErrorCode status = U_ZERO_ERROR; + int32_t canonicalized_len; + + canonicalized_len = uloc_canonicalize(locale, canonicalized, sizeof(canonicalized), &status); + + if (U_FAILURE(status) || canonicalized_len <= 0) { + return NULL; + } + + return estrdup(canonicalized); +} + +static PHP_INI_MH(OnUpdateErrorLevel) +{ + zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); + *p = zend_ini_parse_quantity_warn(new_value, entry->name); + if (*p) { + php_error_docref("session.configuration", E_DEPRECATED, + "Using a value different than 0 for intl.error_level is deprecated," + " as the intl.error_level INI setting is deprecated." + " Instead the intl.use_exceptions INI setting should be enabled to throw exceptions on errors" + " or intl_get_error_code()/intl_get_error_message() should be used to manually deal with errors"); + } + return SUCCESS; +} + /* {{{ INI Settings */ PHP_INI_BEGIN() STD_PHP_INI_ENTRY(LOCALE_INI_NAME, NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_locale, zend_intl_globals, intl_globals) - STD_PHP_INI_ENTRY("intl.error_level", "0", PHP_INI_ALL, OnUpdateLong, error_level, zend_intl_globals, intl_globals) + STD_PHP_INI_ENTRY("intl.error_level", "0", PHP_INI_ALL, OnUpdateErrorLevel, error_level, zend_intl_globals, intl_globals) STD_PHP_INI_BOOLEAN("intl.use_exceptions", "0", PHP_INI_ALL, OnUpdateBool, use_exceptions, zend_intl_globals, intl_globals) PHP_INI_END() /* }}} */ diff --git a/ext/intl/php_intl.h b/ext/intl/php_intl.h index 69772f4a85481..a56c34f3dce44 100644 --- a/ext/intl/php_intl.h +++ b/ext/intl/php_intl.h @@ -68,6 +68,7 @@ PHP_RSHUTDOWN_FUNCTION(intl); PHP_MINFO_FUNCTION(intl); const char *intl_locale_get_default( void ); +char *canonicalize_locale_string(const char* locale); #define PHP_INTL_VERSION PHP_VERSION diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index dfb05a2b50ac5..9a8f036865cd5 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -173,8 +173,7 @@ class IntlException extends Exception /* calendar */ -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ -function intlcal_create_instance($timezone = null, ?string $locale = null): ?IntlCalendar {} +function intlcal_create_instance(IntlTimeZone|DateTimeZone|string|null $timezone = null, ?string $locale = null): ?IntlCalendar {} function intlcal_get_keyword_values_for_locale(string $keyword, string $locale, bool $onlyCommon): IntlIterator|false {} @@ -194,8 +193,7 @@ function intlcal_set_time(IntlCalendar $calendar, float $timestamp): bool {} function intlcal_add(IntlCalendar $calendar, int $field, int $value): bool {} -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ -function intlcal_set_time_zone(IntlCalendar $calendar, $timezone): bool {} +function intlcal_set_time_zone(IntlCalendar $calendar, IntlTimeZone|DateTimeZone|string|null $timezone): bool {} function intlcal_after(IntlCalendar $calendar, IntlCalendar $other): bool {} @@ -328,12 +326,11 @@ function intl_error_name(int $errorCode): string {} /* dateformat */ -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ function datefmt_create( ?string $locale, int $dateType = IntlDateFormatter::FULL, int $timeType = IntlDateFormatter::FULL, - $timezone = null, + IntlTimeZone|DateTimeZone|string|null $timezone = null, IntlCalendar|int|null $calendar = null, ?string $pattern = null ): ?IntlDateFormatter {} @@ -352,8 +349,7 @@ function datefmt_get_calendar_object(IntlDateFormatter $formatter): IntlCalendar function datefmt_get_timezone(IntlDateFormatter $formatter): IntlTimeZone|false {} -/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ -function datefmt_set_timezone(IntlDateFormatter $formatter, $timezone): bool {} +function datefmt_set_timezone(IntlDateFormatter $formatter, IntlTimeZone|DateTimeZone|string|null $timezone): bool {} function datefmt_set_pattern(IntlDateFormatter $formatter, string $pattern): bool {} @@ -431,23 +427,23 @@ function numfmt_get_error_message(NumberFormatter $formatter): string {} function grapheme_strlen(string $string): int|false|null {} -function grapheme_strpos(string $haystack, string $needle, int $offset = 0): int|false {} +function grapheme_strpos(string $haystack, string $needle, int $offset = 0, string $locale = ""): int|false {} -function grapheme_stripos(string $haystack, string $needle, int $offset = 0): int|false {} +function grapheme_stripos(string $haystack, string $needle, int $offset = 0, string $locale = ""): int|false {} -function grapheme_strrpos(string $haystack, string $needle, int $offset = 0): int|false {} +function grapheme_strrpos(string $haystack, string $needle, int $offset = 0, string $locale = ""): int|false {} -function grapheme_strripos(string $haystack, string $needle, int $offset = 0): int|false {} +function grapheme_strripos(string $haystack, string $needle, int $offset = 0, string $locale = ""): int|false {} -function grapheme_substr(string $string, int $offset, ?int $length = null): string|false {} +function grapheme_substr(string $string, int $offset, ?int $length = null, string $locale = ""): string|false {} -function grapheme_strstr(string $haystack, string $needle, bool $beforeNeedle = false): string|false {} +function grapheme_strstr(string $haystack, string $needle, bool $beforeNeedle = false, string $locale = ""): string|false {} -function grapheme_stristr(string $haystack, string $needle, bool $beforeNeedle = false): string|false {} +function grapheme_stristr(string $haystack, string $needle, bool $beforeNeedle = false, string $locale = ""): string|false {} function grapheme_str_split(string $string, int $length = 1): array|false {} -function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1): int|false {} +function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = ""): int|false {} /** @param int $next */ function grapheme_extract(string $haystack, int $size, int $type = GRAPHEME_EXTR_COUNT, int $offset = 0, &$next = null): string|false {} @@ -571,8 +567,7 @@ function intltz_count_equivalent_ids(string $timezoneId): int|false {} function intltz_create_default(): IntlTimeZone {} -/** @param IntlTimeZone|string|int|float|null $countryOrRawOffset */ -function intltz_create_enumeration($countryOrRawOffset = null): IntlIterator|false {} +function intltz_create_enumeration(string|int|null $countryOrRawOffset = null): IntlIterator|false {} function intltz_create_time_zone(string $timezoneId): ?IntlTimeZone {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index b710084910733..f778e4cacf3d4 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,8 +1,8 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0d5b028a1ab8f35e8ee1b51ce3141b6ef782af28 */ + * Stub hash: d9e331c3a1ae46f8eae07ef0d39cb9990e74a0d1 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -40,7 +40,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_intlcal_set_time_zone, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, calendar, IntlCalendar, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_intlcal_after, 0, 2, _IS_BOOL, 0) @@ -280,7 +280,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_datefmt_create, 0, 1, IntlDateFor ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, dateType, IS_LONG, 0, "IntlDateFormatter::FULL") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeType, IS_LONG, 0, "IntlDateFormatter::FULL") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_OBJ_TYPE_MASK(0, calendar, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 1, "null") ZEND_END_ARG_INFO() @@ -312,7 +312,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_datefmt_set_timezone, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, formatter, IntlDateFormatter, 0) - ZEND_ARG_INFO(0, timezone) + ZEND_ARG_OBJ_TYPE_MASK(0, timezone, IntlTimeZone|DateTimeZone, MAY_BE_STRING|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_datefmt_set_pattern, 0, 2, _IS_BOOL, 0) @@ -462,6 +462,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_strpos, 0, 2, MAY_BE_LO ZEND_ARG_TYPE_INFO(0, haystack, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, needle, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, offset, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() #define arginfo_grapheme_stripos arginfo_grapheme_strpos @@ -474,12 +475,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_substr, 0, 2, MAY_BE_ST ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, offset, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_strstr, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, haystack, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, needle, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, beforeNeedle, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() #define arginfo_grapheme_stristr arginfo_grapheme_strstr @@ -495,6 +498,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_levenshtein, 0, 2, MAY_ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, insertion_cost, IS_LONG, 0, "1") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, replacement_cost, IS_LONG, 0, "1") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, deletion_cost, IS_LONG, 0, "1") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, locale, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_grapheme_extract, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) @@ -679,7 +683,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intltz_create_default, 0, 0, Intl ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_intltz_create_enumeration, 0, 0, IntlIterator, MAY_BE_FALSE) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, countryOrRawOffset, "null") + ZEND_ARG_TYPE_MASK(0, countryOrRawOffset, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intltz_create_time_zone, 0, 1, IntlTimeZone, 1) @@ -1223,27 +1227,17 @@ static void register_php_intl_symbols(int module_number) zend_attribute *attribute_Deprecated_func_intlcal_set_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "intlcal_set", sizeof("intlcal_set") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_intlcal_set_0_arg0; - zend_string *attribute_Deprecated_func_intlcal_set_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_intlcal_set_0_arg0, attribute_Deprecated_func_intlcal_set_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_intlcal_set_0->args[0].value, &attribute_Deprecated_func_intlcal_set_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_intlcal_set_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_intlcal_set_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_intlcal_set_0_arg1; zend_string *attribute_Deprecated_func_intlcal_set_0_arg1_str = zend_string_init("use IntlCalendar::set(), IntlCalendar::setDate(), or IntlCalendar::setDateTime() instead", strlen("use IntlCalendar::set(), IntlCalendar::setDate(), or IntlCalendar::setDateTime() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_intlcal_set_0_arg1, attribute_Deprecated_func_intlcal_set_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_intlcal_set_0->args[1].value, &attribute_Deprecated_func_intlcal_set_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_intlcal_set_0->args[1].value, attribute_Deprecated_func_intlcal_set_0_arg1_str); attribute_Deprecated_func_intlcal_set_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_intlgregcal_create_instance_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "intlgregcal_create_instance", sizeof("intlgregcal_create_instance") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_intlgregcal_create_instance_0_arg0; - zend_string *attribute_Deprecated_func_intlgregcal_create_instance_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_intlgregcal_create_instance_0_arg0, attribute_Deprecated_func_intlgregcal_create_instance_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_intlgregcal_create_instance_0->args[0].value, &attribute_Deprecated_func_intlgregcal_create_instance_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_intlgregcal_create_instance_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_intlgregcal_create_instance_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_intlgregcal_create_instance_0_arg1; zend_string *attribute_Deprecated_func_intlgregcal_create_instance_0_arg1_str = zend_string_init("use IntlGregorianCalendar::__construct(), IntlGregorianCalendar::createFromDate(), or IntlGregorianCalendar::createFromDateTime() instead", strlen("use IntlGregorianCalendar::__construct(), IntlGregorianCalendar::createFromDate(), or IntlGregorianCalendar::createFromDateTime() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_intlgregcal_create_instance_0_arg1, attribute_Deprecated_func_intlgregcal_create_instance_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_intlgregcal_create_instance_0->args[1].value, &attribute_Deprecated_func_intlgregcal_create_instance_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_intlgregcal_create_instance_0->args[1].value, attribute_Deprecated_func_intlgregcal_create_instance_0_arg1_str); attribute_Deprecated_func_intlgregcal_create_instance_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } diff --git a/ext/intl/resourcebundle/resourcebundle_class.c b/ext/intl/resourcebundle/resourcebundle_class.c index c64bf1d451849..165e60cc1d3a1 100644 --- a/ext/intl/resourcebundle/resourcebundle_class.c +++ b/ext/intl/resourcebundle/resourcebundle_class.c @@ -72,7 +72,7 @@ static zend_object *ResourceBundle_object_create( zend_class_entry *ce ) /* }}} */ /* {{{ ResourceBundle_ctor */ -static int resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced) +static zend_result resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS) { char *bundlename; size_t bundlename_len = 0; @@ -92,11 +92,6 @@ static int resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling Z_PARAM_BOOL(fallback) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); - if (error_handling != NULL) { - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling); - *error_handling_replaced = 1; - } - if (rb->me) { zend_throw_error(NULL, "ResourceBundle object is already constructed"); return FAILURE; @@ -119,18 +114,18 @@ static int resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb)); } - INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: Cannot load libICU resource bundle"); + INTL_CTOR_CHECK_STATUS(rb, "Cannot load libICU resource bundle"); if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) { char *pbuf; intl_errors_set_code(NULL, INTL_DATA_ERROR_CODE(rb)); - spprintf(&pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource " + spprintf(&pbuf, 0, "Cannot load libICU resource " "'%s' without fallback from %s to %s", bundlename ? bundlename : "(default data)", locale, ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb))); - intl_errors_set_custom_msg(INTL_DATA_ERROR_P(rb), pbuf, 1); + intl_errors_set_custom_msg(INTL_DATA_ERROR_P(rb), pbuf); efree(pbuf); return FAILURE; } @@ -142,18 +137,17 @@ static int resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling /* {{{ ResourceBundle object constructor */ PHP_METHOD( ResourceBundle, __construct ) { - zend_error_handling error_handling; - bool error_handling_replaced = 0; + const bool old_use_exception = INTL_G(use_exceptions); + const zend_long old_error_level = INTL_G(error_level); + INTL_G(use_exceptions) = true; + INTL_G(error_level) = 0; return_value = ZEND_THIS; - if (resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) { - if (!EG(exception)) { - zend_throw_exception(IntlException_ce_ptr, "Constructor failed", 0); - } - } - if (error_handling_replaced) { - zend_restore_error_handling(&error_handling); + if (resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + ZEND_ASSERT(EG(exception)); } + INTL_G(use_exceptions) = old_use_exception; + INTL_G(error_level) = old_error_level; } /* }}} */ @@ -161,7 +155,7 @@ PHP_METHOD( ResourceBundle, __construct ) PHP_FUNCTION( resourcebundle_create ) { object_init_ex( return_value, ResourceBundle_ce_ptr ); - if (resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) { + if (resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { zval_ptr_dtor(return_value); RETURN_NULL(); } @@ -214,7 +208,7 @@ static zval *resource_bundle_array_fetch( } else { spprintf( &pbuf, 0, "Cannot load resource element '%s'", key ); } - intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 ); + intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf); efree(pbuf); RETVAL_NULL(); return return_value; @@ -228,7 +222,7 @@ static zval *resource_bundle_array_fetch( } else { spprintf(&pbuf, 0, "Cannot load element '%s' without fallback from to %s", key, locale); } - intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1); + intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf); efree(pbuf); RETVAL_NULL(); return return_value; @@ -307,8 +301,8 @@ static zend_result resourcebundle_array_count(zend_object *object, zend_long *co if (rb->me == NULL) { intl_errors_set(&rb->error, U_ILLEGAL_ARGUMENT_ERROR, - "Found unconstructed ResourceBundle", 0); - return 0; + "Found unconstructed ResourceBundle"); + return FAILURE; } *count = ures_getSize( rb->me ); diff --git a/ext/intl/spoofchecker/spoofchecker_class.h b/ext/intl/spoofchecker/spoofchecker_class.h index 480eeeb476ffb..a471c055c2ce6 100644 --- a/ext/intl/spoofchecker/spoofchecker_class.h +++ b/ext/intl/spoofchecker/spoofchecker_class.h @@ -73,7 +73,7 @@ extern zend_class_entry *Spoofchecker_ce_ptr; #define SPOOFCHECKER_CHECK_STATUS(co, msg) \ intl_error_set_code(NULL, SPOOFCHECKER_ERROR_CODE(co)); \ if (U_FAILURE(SPOOFCHECKER_ERROR_CODE(co))) { \ - intl_errors_set_custom_msg(SPOOFCHECKER_ERROR_P(co), msg, 0); \ + intl_errors_set_custom_msg(SPOOFCHECKER_ERROR_P(co), msg); \ RETURN_FALSE; \ } \ diff --git a/ext/intl/spoofchecker/spoofchecker_create.c b/ext/intl/spoofchecker/spoofchecker_create.c index c1cecac8412a0..7cb51adef4e24 100644 --- a/ext/intl/spoofchecker/spoofchecker_create.c +++ b/ext/intl/spoofchecker/spoofchecker_create.c @@ -26,17 +26,17 @@ PHP_METHOD(Spoofchecker, __construct) #if U_ICU_VERSION_MAJOR_NUM < 58 int checks; #endif - zend_error_handling error_handling; SPOOFCHECKER_METHOD_INIT_VARS; ZEND_PARSE_PARAMETERS_NONE(); - zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, &error_handling); - SPOOFCHECKER_METHOD_FETCH_OBJECT_NO_CHECK; co->uspoof = uspoof_open(SPOOFCHECKER_ERROR_CODE_P(co)); - INTL_METHOD_CHECK_STATUS(co, "spoofchecker: unable to open ICU Spoof Checker"); + if (U_FAILURE(INTL_DATA_ERROR_CODE(co))) { + zend_throw_exception(IntlException_ce_ptr, + "Spoofchecker::__construct(): unable to open ICU Spoof Checker", 0); + } #if U_ICU_VERSION_MAJOR_NUM >= 58 /* TODO save it into the object for further suspiction check comparison. */ @@ -56,6 +56,5 @@ PHP_METHOD(Spoofchecker, __construct) checks = uspoof_getChecks(co->uspoof, SPOOFCHECKER_ERROR_CODE_P(co)); uspoof_setChecks(co->uspoof, checks & ~USPOOF_SINGLE_SCRIPT, SPOOFCHECKER_ERROR_CODE_P(co)); #endif - zend_restore_error_handling(&error_handling); } /* }}} */ diff --git a/ext/intl/tests/breakiter___construct.phpt b/ext/intl/tests/breakiter___construct.phpt index 74d1b1beaa755..d23f434057961 100644 --- a/ext/intl/tests/breakiter___construct.phpt +++ b/ext/intl/tests/breakiter___construct.phpt @@ -4,12 +4,12 @@ IntlBreakIterator::__construct() should not be callable intl --FILE-- getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Fatal error: Uncaught Error: Call to private IntlBreakIterator::__construct() from global scope in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d +--EXPECT-- +Error: Call to private IntlBreakIterator::__construct() from global scope diff --git a/ext/intl/tests/breakiter___construct_error.phpt b/ext/intl/tests/breakiter___construct_error.phpt index 53a92009d3e04..e0e35f5f4f693 100644 --- a/ext/intl/tests/breakiter___construct_error.phpt +++ b/ext/intl/tests/breakiter___construct_error.phpt @@ -5,53 +5,44 @@ intl --FILE-- getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . "\n"; -} - //missing ; at the end: try { var_dump(new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+')); -} catch (IntlException $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } try { var_dump(new IntlRuleBasedBreakIterator()); -} catch (TypeError $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } try { var_dump(new IntlRuleBasedBreakIterator(1,2,3)); -} catch (TypeError $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } try { var_dump(new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;', array())); -} catch (TypeError $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } try { var_dump(new IntlRuleBasedBreakIterator('[\p{Letter}\uFFFD]+;[:number:]+;', true)); -} catch (IntlException $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } $rbbi = new IntlRuleBasedBreakIterator(".;"); try { $rbbi->__construct(".;"); -} catch (Error $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } ?> ---EXPECTF-- -Exception: IntlRuleBasedBreakIterator::__construct(): unable to create RuleBasedBreakIterator from rules (parse error on line 1, offset 31) in %s on line %d - -Exception: IntlRuleBasedBreakIterator::__construct() expects at least 1 argument, 0 given in %s on line %d - -Exception: IntlRuleBasedBreakIterator::__construct() expects at most 2 arguments, 3 given in %s on line %d - -Exception: IntlRuleBasedBreakIterator::__construct(): Argument #2 ($compiled) must be of type bool, array given in %s on line %d - -Exception: IntlRuleBasedBreakIterator::__construct(): unable to create instance from compiled rules in %s on line %d - -Exception: IntlRuleBasedBreakIterator object is already constructed in %s on line %d +--EXPECT-- +IntlException: IntlRuleBasedBreakIterator::__construct(): unable to create RuleBasedBreakIterator from rules (parse error on line 1, offset 31) +ArgumentCountError: IntlRuleBasedBreakIterator::__construct() expects at least 1 argument, 0 given +ArgumentCountError: IntlRuleBasedBreakIterator::__construct() expects at most 2 arguments, 3 given +TypeError: IntlRuleBasedBreakIterator::__construct(): Argument #2 ($compiled) must be of type bool, array given +IntlException: IntlRuleBasedBreakIterator::__construct(): unable to create instance from compiled rules +Error: IntlRuleBasedBreakIterator object is already constructed diff --git a/ext/intl/tests/breakiter_clone_basic.phpt b/ext/intl/tests/breakiter_clone_basic.phpt index ac9197c105104..7fb7837cb8c89 100644 --- a/ext/intl/tests/breakiter_clone_basic.phpt +++ b/ext/intl/tests/breakiter_clone_basic.phpt @@ -4,7 +4,6 @@ IntlBreakIterator: clone handler intl --FILE-- current()); diff --git a/ext/intl/tests/breakiter_factories_basic.phpt b/ext/intl/tests/breakiter_factories_basic.phpt index 440a0e0f42202..00d49e5760d99 100644 --- a/ext/intl/tests/breakiter_factories_basic.phpt +++ b/ext/intl/tests/breakiter_factories_basic.phpt @@ -2,10 +2,10 @@ IntlBreakIterator factories: basic tests --EXTENSIONS-- intl +--INI-- +intl.default_locale=ja --FILE-- setText('foo bar trans'); diff --git a/ext/intl/tests/breakiter_following_basic.phpt b/ext/intl/tests/breakiter_following_basic.phpt index 0e18502c400ee..872e73aba3c4f 100644 --- a/ext/intl/tests/breakiter_following_basic.phpt +++ b/ext/intl/tests/breakiter_following_basic.phpt @@ -4,8 +4,6 @@ IntlBreakIterator::following(): basic test intl --FILE-- setText('foo bar trans zoo bee'); diff --git a/ext/intl/tests/breakiter_getLocale_basic2.phpt b/ext/intl/tests/breakiter_getLocale_basic2.phpt index ee92043187ae3..2ee223ac52185 100644 --- a/ext/intl/tests/breakiter_getLocale_basic2.phpt +++ b/ext/intl/tests/breakiter_getLocale_basic2.phpt @@ -6,8 +6,6 @@ intl = 0) die('skip for ICU < 64.0'); ?> --FILE-- = 64.0'); ?> --FILE-- 0) die('skip for ICU <= 57.1'); ?> --FILE-- getPartsIterator(); diff --git a/ext/intl/tests/breakiter_getPartsIterator_basic2.phpt b/ext/intl/tests/breakiter_getPartsIterator_basic2.phpt index 96833990dd660..4f516c9abf713 100644 --- a/ext/intl/tests/breakiter_getPartsIterator_basic2.phpt +++ b/ext/intl/tests/breakiter_getPartsIterator_basic2.phpt @@ -8,8 +8,6 @@ if (version_compare(INTL_ICU_VERSION, '57.1') <= 0) die('skip for ICU > 57.1'); ?> --FILE-- getPartsIterator(); diff --git a/ext/intl/tests/breakiter_getPartsIterator_error.phpt b/ext/intl/tests/breakiter_getPartsIterator_error.phpt index 0b2ce3c078f0c..f1a5c18c825a3 100644 --- a/ext/intl/tests/breakiter_getPartsIterator_error.phpt +++ b/ext/intl/tests/breakiter_getPartsIterator_error.phpt @@ -4,7 +4,6 @@ IntlBreakIterator::getPartsIterator(): bad args intl --FILE-- getText()); diff --git a/ext/intl/tests/breakiter_isBoundary_basic.phpt b/ext/intl/tests/breakiter_isBoundary_basic.phpt index 238337b737d54..27a1d2596e294 100644 --- a/ext/intl/tests/breakiter_isBoundary_basic.phpt +++ b/ext/intl/tests/breakiter_isBoundary_basic.phpt @@ -4,8 +4,6 @@ IntlBreakIterator::isBoundary(): basic test intl --FILE-- setText('foo bar trans zoo bee'); diff --git a/ext/intl/tests/breakiter_last_basic.phpt b/ext/intl/tests/breakiter_last_basic.phpt index d3edd504a6e07..6cf579a41e970 100644 --- a/ext/intl/tests/breakiter_last_basic.phpt +++ b/ext/intl/tests/breakiter_last_basic.phpt @@ -4,7 +4,6 @@ IntlBreakIterator::last(): basic test intl --FILE-- setText('foo bar trans'); diff --git a/ext/intl/tests/breakiter_next_basic.phpt b/ext/intl/tests/breakiter_next_basic.phpt index 30d255102aa0f..22726bf400e9b 100644 --- a/ext/intl/tests/breakiter_next_basic.phpt +++ b/ext/intl/tests/breakiter_next_basic.phpt @@ -4,8 +4,6 @@ IntlBreakIterator::next(): basic test intl --FILE-- setText('foo bar trans zoo bee'); diff --git a/ext/intl/tests/breakiter_preceding_basic.phpt b/ext/intl/tests/breakiter_preceding_basic.phpt index ed238eaef20ef..7864f4b3c8969 100644 --- a/ext/intl/tests/breakiter_preceding_basic.phpt +++ b/ext/intl/tests/breakiter_preceding_basic.phpt @@ -8,8 +8,6 @@ if (version_compare(INTL_ICU_VERSION, '57.1') > 0) die('skip for ICU <= 57.1'); ?> --FILE-- setText('foo bar trans zoo bee'); diff --git a/ext/intl/tests/breakiter_preceding_basic2.phpt b/ext/intl/tests/breakiter_preceding_basic2.phpt index 4d7ae1eb2e371..04d2e0d654604 100644 --- a/ext/intl/tests/breakiter_preceding_basic2.phpt +++ b/ext/intl/tests/breakiter_preceding_basic2.phpt @@ -8,8 +8,6 @@ if (version_compare(INTL_ICU_VERSION, '57.1') <= 0) die('skip for ICU > 57.1'); ?> --FILE-- setText('foo bar trans zoo bee'); diff --git a/ext/intl/tests/breakiter_previous_basic.phpt b/ext/intl/tests/breakiter_previous_basic.phpt index fcafe672ad922..3f2976261103e 100644 --- a/ext/intl/tests/breakiter_previous_basic.phpt +++ b/ext/intl/tests/breakiter_previous_basic.phpt @@ -4,8 +4,6 @@ IntlBreakIterator::previous(): basic test intl --FILE-- setText('foo bar trans'); diff --git a/ext/intl/tests/breakiter_setText_basic.phpt b/ext/intl/tests/breakiter_setText_basic.phpt index 8f15f31008da5..1262e4a1e4883 100644 --- a/ext/intl/tests/breakiter_setText_basic.phpt +++ b/ext/intl/tests/breakiter_setText_basic.phpt @@ -4,7 +4,6 @@ IntlBreakIterator::setText(): basic test intl --FILE-- --EXPECT-- bool(false) -string(65) "numfmt_set_symbol: invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" +string(67) "numfmt_set_symbol(): invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" bool(false) -string(65) "numfmt_set_symbol: invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" +string(67) "numfmt_set_symbol(): invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" bool(false) -string(65) "numfmt_set_symbol: invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" +string(67) "numfmt_set_symbol(): invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" bool(false) -string(65) "numfmt_set_symbol: invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" +string(67) "numfmt_set_symbol(): invalid symbol value: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/bug58756_MessageFormatter_variant2.phpt b/ext/intl/tests/bug58756_MessageFormatter_variant2.phpt index 6bfbbd8a2f0aa..c06ba8dd277f1 100644 --- a/ext/intl/tests/bug58756_MessageFormatter_variant2.phpt +++ b/ext/intl/tests/bug58756_MessageFormatter_variant2.phpt @@ -2,6 +2,8 @@ Bug #58756: w.r.t MessageFormatter --EXTENSIONS-- intl +--INI-- +date.timezone=America/New_York --SKIPIF-- --FILE-- compare('h', 'H'); +try { + $a = $c->compare('h', 'H'); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Fatal error: Uncaught Error: Object not initialized in %s:%d -Stack trace: -#0 %s(%d): Collator->compare('h', 'H') -#1 {main} - thrown in %s on line %d +--EXPECT-- +Error: Object not initialized diff --git a/ext/intl/tests/bug60192-getlocale.phpt b/ext/intl/tests/bug60192-getlocale.phpt index fed0d634cc8d0..4d648b3ec718a 100644 --- a/ext/intl/tests/bug60192-getlocale.phpt +++ b/ext/intl/tests/bug60192-getlocale.phpt @@ -12,11 +12,11 @@ class Collator2 extends Collator{ } $c = new Collator2(); -$c->getLocale(Locale::ACTUAL_LOCALE); +try { + $c->getLocale(Locale::ACTUAL_LOCALE); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Fatal error: Uncaught Error: Object not initialized in %s:%d -Stack trace: -#0 %s(%d): Collator->getLocale(0) -#1 {main} - thrown in %s on line %d +--EXPECT-- +Error: Object not initialized diff --git a/ext/intl/tests/bug60192-getsortkey.phpt b/ext/intl/tests/bug60192-getsortkey.phpt index aeadf8db75a5b..39a1c766e7ffd 100644 --- a/ext/intl/tests/bug60192-getsortkey.phpt +++ b/ext/intl/tests/bug60192-getsortkey.phpt @@ -12,11 +12,11 @@ class Collator2 extends Collator{ } $c = new Collator2(); -$c->getSortKey('h'); +try { + $c->getSortKey('h'); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Fatal error: Uncaught Error: Object not initialized in %s:%d -Stack trace: -#0 %s(%d): Collator->getSortKey('h') -#1 {main} - thrown in %s on line %d +--EXPECT-- +Error: Object not initialized diff --git a/ext/intl/tests/bug60192-sort.phpt b/ext/intl/tests/bug60192-sort.phpt index 1166df8161872..e95fd6237cf13 100644 --- a/ext/intl/tests/bug60192-sort.phpt +++ b/ext/intl/tests/bug60192-sort.phpt @@ -13,11 +13,11 @@ class Collator2 extends Collator{ $c = new Collator2(); $a = array('a', 'b'); -$c->sort($a); +try { + $c->sort($a); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Fatal error: Uncaught Error: Object not initialized in %s:%d -Stack trace: -#0 %s(%d): Collator->sort(Array) -#1 {main} - thrown in %s on line %d +--EXPECT-- +Error: Object not initialized diff --git a/ext/intl/tests/bug60192-sortwithsortkeys.phpt b/ext/intl/tests/bug60192-sortwithsortkeys.phpt index 46aacb052ba87..532d153fb5b73 100644 --- a/ext/intl/tests/bug60192-sortwithsortkeys.phpt +++ b/ext/intl/tests/bug60192-sortwithsortkeys.phpt @@ -13,11 +13,11 @@ class Collator2 extends Collator{ $c = new Collator2(); $a = array('a', 'b'); -$c->sortWithSortKeys($a); +try { + $c->sortWithSortKeys($a); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Fatal error: Uncaught Error: Object not initialized in %s:%d -Stack trace: -#0 %s(%d): Collator->sortWithSortKeys(Array) -#1 {main} - thrown in %s on line %d +--EXPECT-- +Error: Object not initialized diff --git a/ext/intl/tests/bug62017.phpt b/ext/intl/tests/bug62017.phpt index 53b0deb4fa7d8..c149b120246d5 100644 --- a/ext/intl/tests/bug62017.phpt +++ b/ext/intl/tests/bug62017.phpt @@ -4,23 +4,20 @@ Bug #62017: datefmt_create with incorrectly encoded timezone leaks pattern intl --FILE-- getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . PHP_EOL; +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } try { - new IntlDateFormatter('', IntlDateFormatter::NONE, IntlDateFormatter::NONE, "Europe/Lisbon", + new IntlDateFormatter('', IntlDateFormatter::NONE, IntlDateFormatter::NONE, "Europe/Lisbon", IntlDateFormatter::GREGORIAN, "\x80"); -} catch (IntlException $e) { - echo PHP_EOL."Exception: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . PHP_EOL; +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } ?> ---EXPECTF-- - -Exception: datefmt_create: Time zone identifier given is not a valid UTF-8 string in %s on line %d - -Exception: IntlDateFormatter::__construct(): datefmt_create: error converting pattern to UTF-16 in %s on line %d +--EXPECT-- +IntlException: datefmt_create(): Time zone identifier given is not a valid UTF-8 string +IntlException: IntlDateFormatter::__construct(): error converting pattern to UTF-16 diff --git a/ext/intl/tests/bug62081.phpt b/ext/intl/tests/bug62081.phpt index d1c066994b6e4..5b6f1d50c9bfc 100644 --- a/ext/intl/tests/bug62081.phpt +++ b/ext/intl/tests/bug62081.phpt @@ -6,13 +6,12 @@ date.timezone=Atlantic/Azores intl --FILE-- __construct('en', 1, 1)); +try { + var_dump($x->__construct('en', 1, 1)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: cannot call constructor twice in %sbug62081.php:4 -Stack trace: -#0 %sbug62081.php(4): IntlDateFormatter->__construct('en', 1, 1) -#1 {main} - thrown in %sbug62081.php on line 4 +--EXPECT-- +IntlException: IntlDateFormatter::__construct(): cannot call constructor twice diff --git a/ext/intl/tests/bug67397.phpt b/ext/intl/tests/bug67397.phpt index 7786c81dd4d00..023f47725ab58 100644 --- a/ext/intl/tests/bug67397.phpt +++ b/ext/intl/tests/bug67397.phpt @@ -5,17 +5,17 @@ intl --FILE-- --EXPECT-- -false -'locale_get_display_name : name too long: U_ILLEGAL_ARGUMENT_ERROR' +bool(false) +string(65) "Locale::getDisplayName(): name too long: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(66) "locale_get_display_name(): name too long: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/bug72533.phpt b/ext/intl/tests/bug72533.phpt index c7cc90f9c3b9a..e294f98213e96 100644 --- a/ext/intl/tests/bug72533.phpt +++ b/ext/intl/tests/bug72533.phpt @@ -5,26 +5,30 @@ intl --FILE-- --EXPECT-- -false -'locale_accept_from_http: locale string too long: U_ILLEGAL_ARGUMENT_ERROR' -'en' +bool(false) +string(74) "Locale::acceptFromHttp(): locale string too long: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(75) "locale_accept_from_http(): locale string too long: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(74) "Locale::acceptFromHttp(): locale string too long: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(75) "locale_accept_from_http(): locale string too long: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/bug75317.phpt b/ext/intl/tests/bug75317.phpt index 1dd96950bb0ea..4df45f37bf804 100644 --- a/ext/intl/tests/bug75317.phpt +++ b/ext/intl/tests/bug75317.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #75317 (UConverter::setDestinationEncoding changes source instead of destinatination) +Bug #75317 (UConverter::setDestinationEncoding changes source instead of destination) --EXTENSIONS-- intl --FILE-- diff --git a/ext/intl/tests/calendar_add_basic.phpt b/ext/intl/tests/calendar_add_basic.phpt index f732f02f358df..9a7a16f844fd2 100644 --- a/ext/intl/tests/calendar_add_basic.phpt +++ b/ext/intl/tests/calendar_add_basic.phpt @@ -2,12 +2,11 @@ IntlCalendar::add() basic test --INI-- date.timezone=Atlantic/Azores +intl.default_locale=nl --EXTENSIONS-- intl --FILE-- --EXPECT-- float(1330578367000) -float(1330578367000) \ No newline at end of file +float(1330578367000) diff --git a/ext/intl/tests/calendar_add_error.phpt b/ext/intl/tests/calendar_add_error.phpt deleted file mode 100644 index a56576df45934..0000000000000 --- a/ext/intl/tests/calendar_add_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::add(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_add(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_add(1, 2, 3) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_before_after_error.phpt b/ext/intl/tests/calendar_before_after_error.phpt deleted file mode 100644 index 8688059124cc7..0000000000000 --- a/ext/intl/tests/calendar_before_after_error.phpt +++ /dev/null @@ -1,77 +0,0 @@ ---TEST-- -IntlCalendar::before()/after(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- -after()); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->before()); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} - -try { - var_dump($c->after(1)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->before(1)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} - -try{ - var_dump($c->after($c, 1)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->before($c, 1)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} - -try { - var_dump(intlcal_after($c)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump(intlcal_before($c)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -?> ---EXPECT-- -error: 0, IntlCalendar::after() expects exactly 1 argument, 0 given - -error: 0, IntlCalendar::before() expects exactly 1 argument, 0 given - -error: 0, IntlCalendar::after(): Argument #1 ($other) must be of type IntlCalendar, int given - -error: 0, IntlCalendar::before(): Argument #1 ($other) must be of type IntlCalendar, int given - -error: 0, IntlCalendar::after() expects exactly 1 argument, 2 given - -error: 0, IntlCalendar::before() expects exactly 1 argument, 2 given - -error: 0, intlcal_after() expects exactly 2 arguments, 1 given - -error: 0, intlcal_before() expects exactly 2 arguments, 1 given diff --git a/ext/intl/tests/calendar_clear_basic.phpt b/ext/intl/tests/calendar_clear_basic.phpt index df3ecc9758968..f9edbac9c03d1 100644 --- a/ext/intl/tests/calendar_clear_basic.phpt +++ b/ext/intl/tests/calendar_clear_basic.phpt @@ -2,10 +2,10 @@ IntlCalendar::clear() basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl --FILE-- clear()); @@ -33,4 +33,4 @@ int(0) int(0) int(0) int(0) -float(-3600000) \ No newline at end of file +float(-3600000) diff --git a/ext/intl/tests/calendar_clear_error.phpt b/ext/intl/tests/calendar_clear_error.phpt index 7880275a7c10f..8f1695564e946 100644 --- a/ext/intl/tests/calendar_clear_error.phpt +++ b/ext/intl/tests/calendar_clear_error.phpt @@ -1,7 +1,5 @@ --TEST-- IntlCalendar::clear(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- @@ -20,13 +18,7 @@ try { echo $e->getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_clear(1, 2)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- IntlCalendar::clear(): Argument #1 ($field) must be a valid field intlcal_clear(): Argument #2 ($field) must be a valid field -intlcal_clear(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_clear_variation1.phpt b/ext/intl/tests/calendar_clear_variation1.phpt index 75f026d0521cb..a485747f4d23f 100644 --- a/ext/intl/tests/calendar_clear_variation1.phpt +++ b/ext/intl/tests/calendar_clear_variation1.phpt @@ -1,7 +1,7 @@ --TEST-- IntlCalendar::clear() 1 arg variation --INI-- -date.timezone=Atlantic/Azores +intl.default_locale=nl --EXTENSIONS-- intl --SKIPIF-- @@ -12,16 +12,14 @@ if (version_compare(INTL_ICU_VERSION, '73.1') >= 0 && version_compare(INTL_ICU_V ?> --FILE-- setTime(strtotime('2012-02-29 05:06:07 +0000') * 1000); -//print_R($intlcal); + var_dump($intlcal->isSet(IntlCalendar::FIELD_MONTH)); var_dump($intlcal->clear(IntlCalendar::FIELD_MONTH)); var_dump($intlcal->isSet(IntlCalendar::FIELD_MONTH)); -//print_R($intlcal); + var_dump( $intlcal->getTime(), strtotime('2012-01-29 05:06:07 +0000') * 1000. diff --git a/ext/intl/tests/calendar_createInstance_basic.phpt b/ext/intl/tests/calendar_createInstance_basic.phpt index c2ddd976094e1..f19f7c0535883 100644 --- a/ext/intl/tests/calendar_createInstance_basic.phpt +++ b/ext/intl/tests/calendar_createInstance_basic.phpt @@ -2,12 +2,11 @@ IntlCalendar::createInstance() basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl +date.timezone=Europe/Amsterdam --FILE-- getTimeZone()); diff --git a/ext/intl/tests/calendar_createInstance_error.phpt b/ext/intl/tests/calendar_createInstance_error.phpt index a48b6b12c2d13..28ade19b8fc8e 100644 --- a/ext/intl/tests/calendar_createInstance_error.phpt +++ b/ext/intl/tests/calendar_createInstance_error.phpt @@ -4,7 +4,6 @@ IntlCalendar::createInstance: bad arguments intl --FILE-- --EXPECT-- -intlcal_create_instance: passed IntlTimeZone is not properly constructed +intlcal_create_instance(): passed IntlTimeZone is not properly constructed diff --git a/ext/intl/tests/calendar_createInstance_variation1.phpt b/ext/intl/tests/calendar_createInstance_variation1.phpt index a963e9ef75907..4c0848d80f1c8 100644 --- a/ext/intl/tests/calendar_createInstance_variation1.phpt +++ b/ext/intl/tests/calendar_createInstance_variation1.phpt @@ -2,12 +2,11 @@ IntlCalendar::createInstance() argument variations --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Amsterdam +intl.default_locale=nl --FILE-- getTimeZone()); diff --git a/ext/intl/tests/calendar_equals_before_after_basic.phpt b/ext/intl/tests/calendar_equals_before_after_basic.phpt index 36999bcb4ebfc..4a7db1a708f9b 100644 --- a/ext/intl/tests/calendar_equals_before_after_basic.phpt +++ b/ext/intl/tests/calendar_equals_before_after_basic.phpt @@ -2,12 +2,11 @@ IntlCalendar::equals(), ::before() and ::after() basic test --INI-- date.timezone=Atlantic/Azores +intl.default_locale=nl --EXTENSIONS-- intl --FILE-- equals()); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->equals(new stdclass)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->equals(1, 2)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} - - -try { - var_dump(intlcal_equals($c, array())); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump(intlcal_equals(1, $c)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -?> ---EXPECT-- -error: 0, IntlCalendar::equals() expects exactly 1 argument, 0 given - -error: 0, IntlCalendar::equals(): Argument #1 ($other) must be of type IntlCalendar, stdClass given - -error: 0, IntlCalendar::equals() expects exactly 1 argument, 2 given - -error: 0, intlcal_equals(): Argument #2 ($other) must be of type IntlCalendar, array given - -error: 0, intlcal_equals(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_fieldDifference_basic.phpt b/ext/intl/tests/calendar_fieldDifference_basic.phpt index 4c910092a729b..cb13fba7072d2 100644 --- a/ext/intl/tests/calendar_fieldDifference_basic.phpt +++ b/ext/intl/tests/calendar_fieldDifference_basic.phpt @@ -2,12 +2,11 @@ IntlCalendar::fieldDifference() basic test --INI-- date.timezone=Atlantic/Azores +intl.default_locale=nl --EXTENSIONS-- intl --FILE-- setTime(strtotime('2012-02-29 05:06:07 +0000') * 1000); @@ -28,4 +27,4 @@ var_dump( --EXPECT-- int(3601) int(6) -int(61) \ No newline at end of file +int(61) diff --git a/ext/intl/tests/calendar_fieldDifference_error.phpt b/ext/intl/tests/calendar_fieldDifference_error.phpt index f538a0db6625b..31070a395290d 100644 --- a/ext/intl/tests/calendar_fieldDifference_error.phpt +++ b/ext/intl/tests/calendar_fieldDifference_error.phpt @@ -1,38 +1,16 @@ --TEST-- IntlCalendar::fieldDifference(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- fieldDifference($c, 2, 3)); -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} var_dump($c->fieldDifference(INF, 2)); +var_dump($c->getErrorMessage()); -try { - var_dump(intlcal_field_difference($c, 0, 1, 2)); -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} -var_dump(intlcal_field_difference(1, 0, 1)); ?> ---EXPECTF-- -IntlCalendar::fieldDifference() expects exactly 2 arguments, 3 given - -Warning: IntlCalendar::fieldDifference(): intlcal_field_difference: Call to ICU method has failed in %s on line %d +--EXPECT-- bool(false) -intlcal_field_difference() expects exactly 3 arguments, 4 given - -Fatal error: Uncaught TypeError: intlcal_field_difference(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_field_difference(1, 0, 1) -#1 {main} - thrown in %s on line %d +string(88) "IntlCalendar::fieldDifference(): Call to ICU method has failed: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/calendar_fromDateTime_basic.phpt b/ext/intl/tests/calendar_fromDateTime_basic.phpt index ba68b267563cb..d91a0e80bc679 100644 --- a/ext/intl/tests/calendar_fromDateTime_basic.phpt +++ b/ext/intl/tests/calendar_fromDateTime_basic.phpt @@ -2,11 +2,11 @@ IntlCalendar::fromDateTime(): basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl_NL +date.timezone=Europe/Lisbon --FILE-- getMessage(), PHP_EOL; } + class A extends DateTime { -function __construct() {} + function __construct() {} } var_dump(IntlCalendar::fromDateTime(new A)); +var_dump(intl_get_error_message()); $date = new DateTime('2012-01-01 00:00:00 +24:00'); var_dump(IntlCalendar::fromDateTime($date)); +var_dump(intl_get_error_message()); $date = new DateTime('2012-01-01 00:00:00 WEST'); var_dump(IntlCalendar::fromDateTime($date)); +var_dump(intl_get_error_message()); + ?> ---EXPECTF-- -threw exception, OK -Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: DateTime object is unconstructed in %s on line %d +--EXPECT-- +DateMalformedStringException: Failed to parse time string (foobar) at position 0 (f): The timezone could not be found in the database NULL - -Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: object has an time zone offset that's too large in %s on line %d +string(88) "IntlCalendar::fromDateTime(): DateTime object is unconstructed: U_ILLEGAL_ARGUMENT_ERROR" NULL - -Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: time zone id 'WEST' extracted from ext/date DateTimeZone not recognized in %s on line %d +string(103) "IntlCalendar::fromDateTime(): object has an time zone offset that's too large: U_ILLEGAL_ARGUMENT_ERROR" NULL +string(127) "IntlCalendar::fromDateTime(): time zone id 'WEST' extracted from ext/date DateTimeZone not recognized: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/calendar_getAvailableLocales_basic.phpt b/ext/intl/tests/calendar_getAvailableLocales_basic.phpt index 38824b0924a22..85e5ed9acf91a 100644 --- a/ext/intl/tests/calendar_getAvailableLocales_basic.phpt +++ b/ext/intl/tests/calendar_getAvailableLocales_basic.phpt @@ -2,10 +2,10 @@ IntlCalendar::getAvailableLocales() basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl --FILE-- 100); @@ -16,4 +16,4 @@ var_dump(in_array('pt', $locales)); ?> --EXPECT-- bool(true) -bool(true) \ No newline at end of file +bool(true) diff --git a/ext/intl/tests/calendar_getDayOfWeekType_basic2.phpt b/ext/intl/tests/calendar_getDayOfWeekType_basic2.phpt index 1694d87c59b49..7097b495da679 100644 --- a/ext/intl/tests/calendar_getDayOfWeekType_basic2.phpt +++ b/ext/intl/tests/calendar_getDayOfWeekType_basic2.phpt @@ -1,13 +1,9 @@ --TEST-- IntlCalendar::getDayOfWeekType() basic test ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- setTime(strtotime('2012-02-29 00:00:00 +0000') * 1000); diff --git a/ext/intl/tests/calendar_getDayOfWeekType_error.phpt b/ext/intl/tests/calendar_getDayOfWeekType_error.phpt index e239f830f17ed..fdea44c17fa8e 100644 --- a/ext/intl/tests/calendar_getDayOfWeekType_error.phpt +++ b/ext/intl/tests/calendar_getDayOfWeekType_error.phpt @@ -1,7 +1,5 @@ --TEST-- IntlCalendar::getDayOfWeekOfType(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- @@ -14,12 +12,6 @@ try { echo $e->getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_get_day_of_week_type(1, 1)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- IntlCalendar::getDayOfWeekType(): Argument #1 ($dayOfWeek) must be a valid day of the week -intlcal_get_day_of_week_type(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_getErrorCode_error.phpt b/ext/intl/tests/calendar_getErrorCode_error.phpt deleted file mode 100644 index cd4c644f1faaa..0000000000000 --- a/ext/intl/tests/calendar_getErrorCode_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getErrorCode(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_error_code(): Argument #1 ($calendar) must be of type IntlCalendar, null given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_error_code(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getErrorCode_getErrorMessage_basic.phpt b/ext/intl/tests/calendar_getErrorCode_getErrorMessage_basic.phpt index 689ec4b16a29a..e1431f5815db0 100644 --- a/ext/intl/tests/calendar_getErrorCode_getErrorMessage_basic.phpt +++ b/ext/intl/tests/calendar_getErrorCode_getErrorMessage_basic.phpt @@ -2,38 +2,35 @@ IntlCalendar::getErrorCode(), ::getErrorMessage() basic test --INI-- date.timezone=Atlantic/Azores +intl.default_locale=nl --EXTENSIONS-- intl --FILE-- getErrorCode(), - intlcal_get_error_code($intlcal), - $intlcal->getErrorMessage(), - intlcal_get_error_message($intlcal) + $intlcal->getErrorCode(), + intlcal_get_error_code($intlcal), + $intlcal->getErrorMessage(), + intlcal_get_error_message($intlcal) ); $intlcal->add(IntlCalendar::FIELD_SECOND, 2147483647); $intlcal->fieldDifference(-PHP_INT_MAX, IntlCalendar::FIELD_SECOND); var_dump( - $intlcal->getErrorCode(), - intlcal_get_error_code($intlcal), - $intlcal->getErrorMessage(), - intlcal_get_error_message($intlcal) + $intlcal->getErrorCode(), + intlcal_get_error_code($intlcal), + $intlcal->getErrorMessage(), + intlcal_get_error_message($intlcal) ); ?> ---EXPECTF-- +--EXPECT-- int(0) int(0) string(12) "U_ZERO_ERROR" string(12) "U_ZERO_ERROR" - -Warning: IntlCalendar::fieldDifference(): intlcal_field_difference: Call to ICU method has failed in %s on line %d int(1) int(1) -string(81) "intlcal_field_difference: Call to ICU method has failed: U_ILLEGAL_ARGUMENT_ERROR" -string(81) "intlcal_field_difference: Call to ICU method has failed: U_ILLEGAL_ARGUMENT_ERROR" +string(88) "IntlCalendar::fieldDifference(): Call to ICU method has failed: U_ILLEGAL_ARGUMENT_ERROR" +string(88) "IntlCalendar::fieldDifference(): Call to ICU method has failed: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/calendar_getErrorMessage_error.phpt b/ext/intl/tests/calendar_getErrorMessage_error.phpt deleted file mode 100644 index c6713290bea33..0000000000000 --- a/ext/intl/tests/calendar_getErrorMessage_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getErrorMessage(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_error_message(): Argument #1 ($calendar) must be of type IntlCalendar, null given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_error_message(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getFirstDayOfWeek_basic.phpt b/ext/intl/tests/calendar_getFirstDayOfWeek_basic.phpt index 0cf0b88527879..ae91595afbab0 100644 --- a/ext/intl/tests/calendar_getFirstDayOfWeek_basic.phpt +++ b/ext/intl/tests/calendar_getFirstDayOfWeek_basic.phpt @@ -2,10 +2,10 @@ IntlCalendar::getFirstDayOfWeek() basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl --FILE-- getFirstDayOfWeek()); @@ -13,4 +13,4 @@ var_dump(intlcal_get_first_day_of_week($intlcal)); ?> --EXPECT-- int(2) -int(2) \ No newline at end of file +int(2) diff --git a/ext/intl/tests/calendar_getFirstDayOfWeek_error.phpt b/ext/intl/tests/calendar_getFirstDayOfWeek_error.phpt deleted file mode 100644 index fb129437a7ce7..0000000000000 --- a/ext/intl/tests/calendar_getFirstDayOfWeek_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getFirstDayOfWeek(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_first_day_of_week(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_first_day_of_week(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getKeywordValuesForLocale_basic.phpt b/ext/intl/tests/calendar_getKeywordValuesForLocale_basic.phpt index e6c05aa4273da..eea0a325b96c2 100644 --- a/ext/intl/tests/calendar_getKeywordValuesForLocale_basic.phpt +++ b/ext/intl/tests/calendar_getKeywordValuesForLocale_basic.phpt @@ -4,27 +4,20 @@ IntlCalendar::getKeywordValuesForLocale() basic test intl --FILE-- 8); var_dump(in_array('japanese', $var)); ?> --EXPECT-- -Array -( - [0] => gregorian -) +array(1) { + [0]=> + string(9) "gregorian" +} bool(true) bool(true) diff --git a/ext/intl/tests/calendar_getLocale_basic.phpt b/ext/intl/tests/calendar_getLocale_basic.phpt index 92311ad41911e..9c3eece1c5fa8 100644 --- a/ext/intl/tests/calendar_getLocale_basic.phpt +++ b/ext/intl/tests/calendar_getLocale_basic.phpt @@ -2,10 +2,10 @@ IntlCalendar::getLocale() basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl --FILE-- getLocale(Locale::ACTUAL_LOCALE)); diff --git a/ext/intl/tests/calendar_getLocale_error.phpt b/ext/intl/tests/calendar_getLocale_error.phpt deleted file mode 100644 index 7b51734fe2710..0000000000000 --- a/ext/intl/tests/calendar_getLocale_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getLocale(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught ArgumentCountError: intlcal_get_locale() expects exactly 2 arguments, 1 given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_locale(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getMinimalDaysInFirstWeek_basic.phpt b/ext/intl/tests/calendar_getMinimalDaysInFirstWeek_basic.phpt index 42f7a56b440eb..fe34cd04899bd 100644 --- a/ext/intl/tests/calendar_getMinimalDaysInFirstWeek_basic.phpt +++ b/ext/intl/tests/calendar_getMinimalDaysInFirstWeek_basic.phpt @@ -2,10 +2,10 @@ IntlCalendar::getMinimalDaysInFirstWeek() basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl --FILE-- getMinimalDaysInFirstWeek()); diff --git a/ext/intl/tests/calendar_getMinimalDaysInFirstWeek_error.phpt b/ext/intl/tests/calendar_getMinimalDaysInFirstWeek_error.phpt deleted file mode 100644 index 53ff687ee8c40..0000000000000 --- a/ext/intl/tests/calendar_getMinimalDaysInFirstWeek_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getMinimalDaysInFirstWeek(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_minimal_days_in_first_week(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_minimal_days_in_first_week(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getNow_basic.phpt b/ext/intl/tests/calendar_getNow_basic.phpt index ddc21208b0c68..2b5eb8963426a 100644 --- a/ext/intl/tests/calendar_getNow_basic.phpt +++ b/ext/intl/tests/calendar_getNow_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::getNow() basic test intl --FILE-- ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_skipped_wall_time_option(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_skipped_wall_time_option(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getTimeZone_basic.phpt b/ext/intl/tests/calendar_getTimeZone_basic.phpt index 7d19f19be7cf1..4b98c1d648dd9 100644 --- a/ext/intl/tests/calendar_getTimeZone_basic.phpt +++ b/ext/intl/tests/calendar_getTimeZone_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::getTimeZone() basic test intl --FILE-- getTimeZone()); diff --git a/ext/intl/tests/calendar_getTimeZone_error.phpt b/ext/intl/tests/calendar_getTimeZone_error.phpt deleted file mode 100644 index fad3a5e7e7454..0000000000000 --- a/ext/intl/tests/calendar_getTimeZone_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getTimeZone(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_time_zone(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_time_zone(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getTime_basic.phpt b/ext/intl/tests/calendar_getTime_basic.phpt index 97e31011e7672..754dfde01474e 100644 --- a/ext/intl/tests/calendar_getTime_basic.phpt +++ b/ext/intl/tests/calendar_getTime_basic.phpt @@ -1,13 +1,9 @@ --TEST-- IntlCalendar::getTime() basic test ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- clear(); @@ -22,4 +18,4 @@ var_dump((float)$time*1000, $intlcal->getTime()); ?> --EXPECT-- float(1330473600000) -float(1330473600000) \ No newline at end of file +float(1330473600000) diff --git a/ext/intl/tests/calendar_getTime_error.phpt b/ext/intl/tests/calendar_getTime_error.phpt deleted file mode 100644 index 0f6a470637b17..0000000000000 --- a/ext/intl/tests/calendar_getTime_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getTime(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_time(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_time(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getType_basic.phpt b/ext/intl/tests/calendar_getType_basic.phpt index c1ae1d242cded..bca65507eadd6 100644 --- a/ext/intl/tests/calendar_getType_basic.phpt +++ b/ext/intl/tests/calendar_getType_basic.phpt @@ -1,19 +1,15 @@ --TEST-- IntlCalendar::getType() basic test ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- getType()); +var_dump($intlcal->getType()); $intlcal = IntlCalendar::createInstance(null, "nl_NL@calendar=hebrew"); -VAR_DUMP(intlcal_get_type($intlcal)); +var_dump(intlcal_get_type($intlcal)); ?> --EXPECT-- string(9) "gregorian" -string(6) "hebrew" \ No newline at end of file +string(6) "hebrew" diff --git a/ext/intl/tests/calendar_getType_error.phpt b/ext/intl/tests/calendar_getType_error.phpt deleted file mode 100644 index 78d0a57f1549e..0000000000000 --- a/ext/intl/tests/calendar_getType_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::getType(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_get_type(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_get_type(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_getWeekendTransition_basic.phpt b/ext/intl/tests/calendar_getWeekendTransition_basic.phpt index 2045dc6e3416d..4e5cfd41f4cd9 100644 --- a/ext/intl/tests/calendar_getWeekendTransition_basic.phpt +++ b/ext/intl/tests/calendar_getWeekendTransition_basic.phpt @@ -6,8 +6,6 @@ date.timezone=Atlantic/Azores intl --FILE-- getWeekendTransition(IntlCalendar::DOW_SUNDAY)); diff --git a/ext/intl/tests/calendar_getWeekendTransition_error.phpt b/ext/intl/tests/calendar_getWeekendTransition_error.phpt index 9bd269c9a0831..a5e020a6803a0 100644 --- a/ext/intl/tests/calendar_getWeekendTransition_error.phpt +++ b/ext/intl/tests/calendar_getWeekendTransition_error.phpt @@ -1,12 +1,9 @@ --TEST-- IntlCalendar::getWeekendTransition(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_get_weekend_transition(1, 1)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} - ?> --EXPECT-- IntlCalendar::getWeekendTransition(): Argument #1 ($dayOfWeek) must be a valid day of the week -intlcal_get_weekend_transition(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_getXMaximum_basic.phpt b/ext/intl/tests/calendar_getXMaximum_basic.phpt index 5e5ae778b2d2f..35b8a202d3976 100644 --- a/ext/intl/tests/calendar_getXMaximum_basic.phpt +++ b/ext/intl/tests/calendar_getXMaximum_basic.phpt @@ -1,13 +1,9 @@ --TEST-- IntlCalendar::getMaximum(), ::getActualMaximum(), ::getLeastMaximum() basic test ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- setTime(strtotime('2012-02-29 05:06:07 +0000') * 1000); @@ -27,4 +23,4 @@ int(28) int(29) int(29) int(31) -int(31) \ No newline at end of file +int(31) diff --git a/ext/intl/tests/calendar_getXMinimum_basic.phpt b/ext/intl/tests/calendar_getXMinimum_basic.phpt index c8b6c2e978786..671acc6806af6 100644 --- a/ext/intl/tests/calendar_getXMinimum_basic.phpt +++ b/ext/intl/tests/calendar_getXMinimum_basic.phpt @@ -1,13 +1,9 @@ --TEST-- IntlCalendar::getMinimum(), ::getActualMinimum(), ::getGreatestMinimum() basic test ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- setTime(strtotime('2012-02-29 05:06:07 +0000') * 1000); @@ -27,4 +23,4 @@ int(1) int(1) int(1) int(1) -int(1) \ No newline at end of file +int(1) diff --git a/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt b/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt index 1cab590955d9d..30365162820ce 100644 --- a/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt +++ b/ext/intl/tests/calendar_get_Least_Greatest_Minimum_Maximum_error.phpt @@ -1,7 +1,5 @@ --TEST-- IntlCalendar::get/Least/Greatest/Minimum/Maximum(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- @@ -51,26 +49,6 @@ try { echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_get_least_maximum(1, 1)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_maximum(1, 1)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_greatest_minimum(1, -1)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_minimum(1, -1)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- ValueError: 0, IntlCalendar::getLeastMaximum(): Argument #1 ($field) must be a valid field @@ -81,7 +59,3 @@ ValueError: 0, intlcal_get_least_maximum(): Argument #2 ($field) must be a valid ValueError: 0, intlcal_get_maximum(): Argument #2 ($field) must be a valid field ValueError: 0, intlcal_get_greatest_minimum(): Argument #2 ($field) must be a valid field ValueError: 0, intlcal_get_minimum(): Argument #2 ($field) must be a valid field -TypeError: 0, intlcal_get_least_maximum(): Argument #1 ($calendar) must be of type IntlCalendar, int given -TypeError: 0, intlcal_get_maximum(): Argument #1 ($calendar) must be of type IntlCalendar, int given -TypeError: 0, intlcal_get_greatest_minimum(): Argument #1 ($calendar) must be of type IntlCalendar, int given -TypeError: 0, intlcal_get_minimum(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_get_basic.phpt b/ext/intl/tests/calendar_get_basic.phpt index b22092010b334..37a61b83d0b42 100644 --- a/ext/intl/tests/calendar_get_basic.phpt +++ b/ext/intl/tests/calendar_get_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::get() basic test intl --FILE-- set(IntlCalendar::FIELD_DAY_OF_MONTH, 4); @@ -16,4 +14,4 @@ var_dump(intlcal_get($intlcal, IntlCalendar::FIELD_DAY_OF_MONTH)); ?> --EXPECT-- int(4) -int(4) \ No newline at end of file +int(4) diff --git a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error.phpt b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error.phpt index 9d40f9ec104ee..475c064022252 100644 --- a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error.phpt +++ b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error.phpt @@ -1,7 +1,5 @@ --TEST-- IntlCalendar::get/getActualMaximum/getActualMinimum(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- diff --git a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt index 0cfb77a8947ef..10eb7f8029b87 100644 --- a/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt +++ b/ext/intl/tests/calendar_get_getActualMaximum_Minumum_error2.phpt @@ -1,7 +1,5 @@ --TEST-- IntlCalendar::get/getActualMaximum/getActualMinimum(): bad arguments (procedural) ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- @@ -9,22 +7,6 @@ intl $c = new IntlGregorianCalendar(NULL, 'pt_PT'); -try { - var_dump(intlcal_get($c)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_actual_maximum($c)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_actual_minimum($c)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} - try { var_dump(intlcal_get($c, -1)); } catch (Error $e) { @@ -41,48 +23,8 @@ try { echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_get($c, "s")); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_actual_maximum($c, "s")); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_actual_minimum($c, "s")); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} - -try { - var_dump(intlcal_get(1)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_actual_maximum(1)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} -try { - var_dump(intlcal_get_actual_minimum(1)); -} catch (Error $e) { - echo get_class($e) . ': ' . $e->getCode() . ', ' . $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- -ArgumentCountError: 0, intlcal_get() expects exactly 2 arguments, 1 given -ArgumentCountError: 0, intlcal_get_actual_maximum() expects exactly 2 arguments, 1 given -ArgumentCountError: 0, intlcal_get_actual_minimum() expects exactly 2 arguments, 1 given ValueError: 0, intlcal_get(): Argument #2 ($field) must be a valid field ValueError: 0, intlcal_get_actual_maximum(): Argument #2 ($field) must be a valid field ValueError: 0, intlcal_get_actual_minimum(): Argument #2 ($field) must be a valid field -TypeError: 0, intlcal_get(): Argument #2 ($field) must be of type int, string given -TypeError: 0, intlcal_get_actual_maximum(): Argument #2 ($field) must be of type int, string given -TypeError: 0, intlcal_get_actual_minimum(): Argument #2 ($field) must be of type int, string given -ArgumentCountError: 0, intlcal_get() expects exactly 2 arguments, 1 given -ArgumentCountError: 0, intlcal_get_actual_maximum() expects exactly 2 arguments, 1 given -ArgumentCountError: 0, intlcal_get_actual_minimum() expects exactly 2 arguments, 1 given diff --git a/ext/intl/tests/calendar_get_setRepeatedWallTimeOption_basic.phpt b/ext/intl/tests/calendar_get_setRepeatedWallTimeOption_basic.phpt index 146885b37700e..249f39b7f19d9 100644 --- a/ext/intl/tests/calendar_get_setRepeatedWallTimeOption_basic.phpt +++ b/ext/intl/tests/calendar_get_setRepeatedWallTimeOption_basic.phpt @@ -2,12 +2,11 @@ IntlCalendar::get/setRepeatedWallTimeOption(): basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=nl +date.timezone=Europe/Amsterdam --FILE-- setTime(strtotime('2012-01-01') * 1000); @@ -17,4 +13,4 @@ var_dump(intlcal_in_daylight_time($intlcal)); ?> --EXPECT-- bool(false) -bool(true) \ No newline at end of file +bool(true) diff --git a/ext/intl/tests/calendar_inDaylightTime_error.phpt b/ext/intl/tests/calendar_inDaylightTime_error.phpt deleted file mode 100644 index 7dd6d9c8803eb..0000000000000 --- a/ext/intl/tests/calendar_inDaylightTime_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::inDaylightTime(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_in_daylight_time(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_in_daylight_time(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_isEquivalentTo_basic.phpt b/ext/intl/tests/calendar_isEquivalentTo_basic.phpt index e9c0a6ec575d7..bb01fcfa1f9ed 100644 --- a/ext/intl/tests/calendar_isEquivalentTo_basic.phpt +++ b/ext/intl/tests/calendar_isEquivalentTo_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::isEquivalentTo() basic test intl --FILE-- isEquivalentTo(0)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->isEquivalentTo($c, 1)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->isEquivalentTo(1)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} - -try { - var_dump(intlcal_is_equivalent_to($c)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump(intlcal_is_equivalent_to($c, 1)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump(intlcal_is_equivalent_to(1, $c)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -?> ---EXPECT-- -error: 0, IntlCalendar::isEquivalentTo(): Argument #1 ($other) must be of type IntlCalendar, int given - -error: 0, IntlCalendar::isEquivalentTo() expects exactly 1 argument, 2 given - -error: 0, IntlCalendar::isEquivalentTo(): Argument #1 ($other) must be of type IntlCalendar, int given - -error: 0, intlcal_is_equivalent_to() expects exactly 2 arguments, 1 given - -error: 0, intlcal_is_equivalent_to(): Argument #2 ($other) must be of type IntlCalendar, int given - -error: 0, intlcal_is_equivalent_to(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_isLenient_error.phpt b/ext/intl/tests/calendar_isLenient_error.phpt deleted file mode 100644 index 4011c11cdd896..0000000000000 --- a/ext/intl/tests/calendar_isLenient_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::isLenient(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_is_lenient(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_is_lenient(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_isSet_basic.phpt b/ext/intl/tests/calendar_isSet_basic.phpt index 69895d9e93d88..2f6a8b22a3917 100644 --- a/ext/intl/tests/calendar_isSet_basic.phpt +++ b/ext/intl/tests/calendar_isSet_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::isSet() basic test intl --FILE-- isSet(IntlCalendar::FIELD_MINUTE)); @@ -17,4 +15,4 @@ var_dump(intlcal_is_set($intlcal, IntlCalendar::FIELD_MINUTE)); --EXPECT-- bool(true) bool(false) -bool(true) \ No newline at end of file +bool(true) diff --git a/ext/intl/tests/calendar_isSet_error.phpt b/ext/intl/tests/calendar_isSet_error.phpt index 9f1361b8dce1a..7f289f073ae03 100644 --- a/ext/intl/tests/calendar_isSet_error.phpt +++ b/ext/intl/tests/calendar_isSet_error.phpt @@ -1,7 +1,5 @@ --TEST-- IntlCalendar::isSet(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- @@ -15,12 +13,6 @@ try { echo $e->getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_is_set(1, 2)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- IntlCalendar::isSet(): Argument #1 ($field) must be a valid field -intlcal_is_set(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_isWeekend_basic.phpt b/ext/intl/tests/calendar_isWeekend_basic.phpt index 83408b6283b8a..9479bdc0298f6 100644 --- a/ext/intl/tests/calendar_isWeekend_basic.phpt +++ b/ext/intl/tests/calendar_isWeekend_basic.phpt @@ -1,13 +1,9 @@ --TEST-- IntlCalendar::isWeekend basic test ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- isWeekend(strtotime('2012-02-29 12:00:00 +0000') * 1000)); diff --git a/ext/intl/tests/calendar_isWeekend_error.phpt b/ext/intl/tests/calendar_isWeekend_error.phpt deleted file mode 100644 index d1d49149bf134..0000000000000 --- a/ext/intl/tests/calendar_isWeekend_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::isWeekend(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_is_weekend(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_is_weekend(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_is_set_lenient_basic.phpt b/ext/intl/tests/calendar_is_set_lenient_basic.phpt index 4ec0d8cd01ea7..e516050f27f74 100644 --- a/ext/intl/tests/calendar_is_set_lenient_basic.phpt +++ b/ext/intl/tests/calendar_is_set_lenient_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::isLenient(), ::setLenient() basic test intl --FILE-- isLenient()); @@ -21,4 +19,4 @@ bool(true) bool(true) bool(false) bool(true) -bool(true) \ No newline at end of file +bool(true) diff --git a/ext/intl/tests/calendar_roll_basic.phpt b/ext/intl/tests/calendar_roll_basic.phpt index 3a77bafec3ec5..a8b088ec384fa 100644 --- a/ext/intl/tests/calendar_roll_basic.phpt +++ b/ext/intl/tests/calendar_roll_basic.phpt @@ -6,8 +6,6 @@ date.timezone=Atlantic/Azores intl --FILE-- roll(IntlCalendar::FIELD_DAY_OF_MONTH, 2)); diff --git a/ext/intl/tests/calendar_roll_error.phpt b/ext/intl/tests/calendar_roll_error.phpt index 721297f0458b2..4c05c17a5f814 100644 --- a/ext/intl/tests/calendar_roll_error.phpt +++ b/ext/intl/tests/calendar_roll_error.phpt @@ -1,7 +1,5 @@ --TEST-- IntlCalendar::roll(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- @@ -15,12 +13,6 @@ try { echo $e->getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_roll(1, 2, 3)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- IntlCalendar::roll(): Argument #1 ($field) must be a valid field -intlcal_roll(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_roll_variation1.phpt b/ext/intl/tests/calendar_roll_variation1.phpt index a496d6f2e5472..d79d5dbb59851 100644 --- a/ext/intl/tests/calendar_roll_variation1.phpt +++ b/ext/intl/tests/calendar_roll_variation1.phpt @@ -6,8 +6,6 @@ date.timezone=Atlantic/Azores intl --FILE-- roll(IntlCalendar::FIELD_DAY_OF_MONTH, true)); diff --git a/ext/intl/tests/calendar_setFirstDayOfWeek_basic.phpt b/ext/intl/tests/calendar_setFirstDayOfWeek_basic.phpt index 88b2d53ca6cf2..a77b00ce640e6 100644 --- a/ext/intl/tests/calendar_setFirstDayOfWeek_basic.phpt +++ b/ext/intl/tests/calendar_setFirstDayOfWeek_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::setFirstDayOfWeek() basic test intl --FILE-- getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_set_first_day_of_week(1, 2)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- IntlCalendar::setFirstDayOfWeek(): Argument #1 ($dayOfWeek) must be a valid day of the week intlcal_set_first_day_of_week(): Argument #2 ($dayOfWeek) must be a valid day of the week -intlcal_set_first_day_of_week(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_setLenient_error.phpt b/ext/intl/tests/calendar_setLenient_error.phpt deleted file mode 100644 index 13ecebc5fd5b9..0000000000000 --- a/ext/intl/tests/calendar_setLenient_error.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -IntlCalendar::setLenient(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlcal_set_lenient(): Argument #1 ($calendar) must be of type IntlCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlcal_set_lenient(1, false) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_setMinimalDaysInFirstWeek_basic.phpt b/ext/intl/tests/calendar_setMinimalDaysInFirstWeek_basic.phpt index 7d47f315ae012..5ac2eb5899949 100644 --- a/ext/intl/tests/calendar_setMinimalDaysInFirstWeek_basic.phpt +++ b/ext/intl/tests/calendar_setMinimalDaysInFirstWeek_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::setMinimalDaysInFirstWeek() basic test intl --FILE-- getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_set_minimal_days_in_first_week(1, 2)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- IntlCalendar::setMinimalDaysInFirstWeek(): Argument #1 ($days) must be between 1 and 7 intlcal_set_minimal_days_in_first_week(): Argument #2 ($days) must be between 1 and 7 -intlcal_set_minimal_days_in_first_week(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_setSkipped_RepeatedWallTimeOption_error.phpt b/ext/intl/tests/calendar_setSkipped_RepeatedWallTimeOption_error.phpt index 0e3c10d7f55a9..8019c81870da1 100644 --- a/ext/intl/tests/calendar_setSkipped_RepeatedWallTimeOption_error.phpt +++ b/ext/intl/tests/calendar_setSkipped_RepeatedWallTimeOption_error.phpt @@ -1,12 +1,9 @@ --TEST-- IntlCalendar::setSkipped/RepeatedWallTimeOption(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_set_repeated_wall_time_option(1, 1)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECT-- IntlCalendar::setSkippedWallTimeOption(): Argument #1 ($option) must be one of IntlCalendar::WALLTIME_FIRST, IntlCalendar::WALLTIME_LAST, or IntlCalendar::WALLTIME_NEXT_VALID IntlCalendar::setRepeatedWallTimeOption(): Argument #1 ($option) must be either IntlCalendar::WALLTIME_FIRST or IntlCalendar::WALLTIME_LAST -intlcal_set_repeated_wall_time_option(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_setTimeZone_basic.phpt b/ext/intl/tests/calendar_setTimeZone_basic.phpt index aacc384087dc0..bd0be9e87818b 100644 --- a/ext/intl/tests/calendar_setTimeZone_basic.phpt +++ b/ext/intl/tests/calendar_setTimeZone_basic.phpt @@ -4,8 +4,6 @@ IntlCalendar::setTimeZone() basic test intl --FILE-- getTimeZone()->getID()); diff --git a/ext/intl/tests/calendar_setTimeZone_error.phpt b/ext/intl/tests/calendar_setTimeZone_error.phpt deleted file mode 100644 index 0cf7939e2de65..0000000000000 --- a/ext/intl/tests/calendar_setTimeZone_error.phpt +++ /dev/null @@ -1,49 +0,0 @@ ---TEST-- -IntlCalendar::setTimeZone(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- -setTimeZone($gmt, 2)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try { - var_dump($c->setTimeZone()); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} - -try{ - var_dump(intlcal_set_time_zone($c, 1, 2)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -try{ - var_dump(intlcal_set_time_zone(1, $gmt)); -} catch (Error $ex) { - echo "error: " . $ex->getCode() . ", " . $ex->getMessage() . "\n\n"; -} -?> ---EXPECT-- -error: 0, IntlCalendar::setTimeZone() expects exactly 1 argument, 2 given - -error: 0, IntlCalendar::setTimeZone() expects exactly 1 argument, 0 given - -error: 0, intlcal_set_time_zone() expects exactly 2 arguments, 3 given - -error: 0, intlcal_set_time_zone(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_setTimeZone_error2.phpt b/ext/intl/tests/calendar_setTimeZone_error2.phpt index c76867b695e40..6b65aa1a0e7c1 100644 --- a/ext/intl/tests/calendar_setTimeZone_error2.phpt +++ b/ext/intl/tests/calendar_setTimeZone_error2.phpt @@ -2,25 +2,28 @@ IntlCalendar::setTimeZone(): valid time zones for DateTime but not ICU --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Amsterdam +intl.default_locale=nl --FILE-- setTimeZone($pstdate->getTimeZone()); +var_dump($intlcal->setTimeZone($pstdate->getTimeZone())); +var_dump($intlcal->getErrorMessage()); var_dump($intlcal->getTimeZone()->getID()); $pstdate = new DateTime('2012-01-01 00:00:00 +24:00'); -$intlcal->setTimeZone($pstdate->getTimeZone()); +var_dump($intlcal->setTimeZone($pstdate->getTimeZone())); +var_dump($intlcal->getErrorMessage()); var_dump($intlcal->getTimeZone()->getID()); ?> ---EXPECTF-- -Warning: IntlCalendar::setTimeZone(): intlcal_set_time_zone: time zone id 'WEST' extracted from ext/date DateTimeZone not recognized in %s on line %d +--EXPECT-- +bool(false) +string(126) "IntlCalendar::setTimeZone(): time zone id 'WEST' extracted from ext/date DateTimeZone not recognized: U_ILLEGAL_ARGUMENT_ERROR" string(16) "Europe/Amsterdam" - -Warning: IntlCalendar::setTimeZone(): intlcal_set_time_zone: object has an time zone offset that's too large in %s on line %d +bool(false) +string(102) "IntlCalendar::setTimeZone(): object has an time zone offset that's too large: U_ILLEGAL_ARGUMENT_ERROR" string(16) "Europe/Amsterdam" diff --git a/ext/intl/tests/calendar_setTimeZone_variation1.phpt b/ext/intl/tests/calendar_setTimeZone_variation1.phpt index 820fd2fd21c02..01d933b9b9af1 100644 --- a/ext/intl/tests/calendar_setTimeZone_variation1.phpt +++ b/ext/intl/tests/calendar_setTimeZone_variation1.phpt @@ -4,8 +4,6 @@ IntlCalendar::setTimeZone() variation with NULL arg intl --FILE-- getTimeZone()->getID()); @@ -23,4 +21,4 @@ var_dump($intlcal->get(IntlCalendar::FIELD_ZONE_OFFSET)); Europe/Amsterdam int(3600000) Europe/Amsterdam -int(3600000) \ No newline at end of file +int(3600000) diff --git a/ext/intl/tests/calendar_setTimeZone_variation2.phpt b/ext/intl/tests/calendar_setTimeZone_variation2.phpt index 25ec03c1f576c..e9866e88c6880 100644 --- a/ext/intl/tests/calendar_setTimeZone_variation2.phpt +++ b/ext/intl/tests/calendar_setTimeZone_variation2.phpt @@ -4,9 +4,6 @@ IntlCalendar::setTimeZone(): different ways to specify time zone intl --FILE-- setTimeZone('Europe/Paris'); diff --git a/ext/intl/tests/calendar_setTime_basic.phpt b/ext/intl/tests/calendar_setTime_basic.phpt index 41f3e0a964ede..045d312e8604f 100644 --- a/ext/intl/tests/calendar_setTime_basic.phpt +++ b/ext/intl/tests/calendar_setTime_basic.phpt @@ -1,13 +1,9 @@ --TEST-- IntlCalendar::setTime() basic test ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- ---EXPECTF-- -Fatal error: Uncaught ArgumentCountError: intlcal_set_time() expects exactly 2 arguments, 1 given in %s:%d -Stack trace: -#0 %s(%d): intlcal_set_time(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/calendar_set_basic.phpt b/ext/intl/tests/calendar_set_basic.phpt index 8c410bc3b75be..1cd946fdd3c9b 100644 --- a/ext/intl/tests/calendar_set_basic.phpt +++ b/ext/intl/tests/calendar_set_basic.phpt @@ -6,8 +6,6 @@ date.timezone=Atlantic/Azores intl --FILE-- set(IntlCalendar::FIELD_DAY_OF_MONTH, 2)); diff --git a/ext/intl/tests/calendar_set_error.phpt b/ext/intl/tests/calendar_set_error.phpt index 4494c67c9540b..d29442f519509 100644 --- a/ext/intl/tests/calendar_set_error.phpt +++ b/ext/intl/tests/calendar_set_error.phpt @@ -1,12 +1,9 @@ --TEST-- IntlCalendar::set(): bad arguments ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- getMessage() . \PHP_EOL; } -try { - var_dump(intlcal_set(1, 2, 3)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> --EXPECTF-- Deprecated: Calling IntlCalendar::set() with more than 2 arguments is deprecated, use either IntlCalendar::setDate() or IntlCalendar::setDateTime() instead in %s on line %d @@ -50,6 +42,3 @@ IntlCalendar::set(): Argument #1 ($year) must be a valid field Deprecated: Function intlcal_set() is deprecated since 8.4, use IntlCalendar::set(), IntlCalendar::setDate(), or IntlCalendar::setDateTime() instead in %s on line %d intlcal_set(): Argument #2 ($year) must be a valid field - -Deprecated: Function intlcal_set() is deprecated since 8.4, use IntlCalendar::set(), IntlCalendar::setDate(), or IntlCalendar::setDateTime() instead in %s on line %d -intlcal_set(): Argument #1 ($calendar) must be of type IntlCalendar, int given diff --git a/ext/intl/tests/calendar_set_variation1.phpt b/ext/intl/tests/calendar_set_variation1.phpt index 520c909487351..1d23a8d03c5de 100644 --- a/ext/intl/tests/calendar_set_variation1.phpt +++ b/ext/intl/tests/calendar_set_variation1.phpt @@ -1,13 +1,9 @@ --TEST-- IntlCalendar::set() argument variations ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --FILE-- clear(); diff --git a/ext/intl/tests/calendar_toDateTime_basic.phpt b/ext/intl/tests/calendar_toDateTime_basic.phpt index 391d13005c69e..09942cbe3d8fa 100644 --- a/ext/intl/tests/calendar_toDateTime_basic.phpt +++ b/ext/intl/tests/calendar_toDateTime_basic.phpt @@ -2,11 +2,10 @@ IntlCalendar::toDateTime(): basic test --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Lisbon --FILE-- toDateTime()); -} catch (Exception $e) { -var_dump("exception: {$e->getMessage()}"); + var_dump($cal->toDateTime()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; + $previous = $e->getPrevious(); + echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL; } try { var_dump(intlcal_to_date_time($cal)); -} catch (\Exception $e) { - var_dump($e->getMessage()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; + $previous = $e->getPrevious(); + echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL; } $cal = IntlCalendar::createInstance("Etc/Unknown"); try { var_dump($cal->toDateTime()); -} catch (\Exception $e) { - var_dump($e->getMessage()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; + $previous = $e->getPrevious(); + echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL; } try { var_dump(intlcal_to_date_time($cal)); -} catch (\Exception $e) { - var_dump($e->getMessage()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; + $previous = $e->getPrevious(); + echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL; } -try { - var_dump(intlcal_to_date_time(3)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} ?> ---EXPECTF-- -Warning: IntlCalendar::toDateTime(): intlcal_to_date_time: DateTimeZone constructor threw exception in %s on line %d -string(77) "exception: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)" - -Warning: intlcal_to_date_time(): intlcal_to_date_time: DateTimeZone constructor threw exception in %s on line %d -string(66) "DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)" - -Warning: IntlCalendar::toDateTime(): intlcal_to_date_time: DateTimeZone constructor threw exception in %s on line %d -string(66) "DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)" - -Warning: intlcal_to_date_time(): intlcal_to_date_time: DateTimeZone constructor threw exception in %s on line %d -string(66) "DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)" -intlcal_to_date_time(): Argument #1 ($calendar) must be of type IntlCalendar, int given +--EXPECT-- +IntlException: DateTimeZone constructor threw exception + DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown) +IntlException: DateTimeZone constructor threw exception + DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown) +IntlException: DateTimeZone constructor threw exception + DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown) +IntlException: DateTimeZone constructor threw exception + DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown) diff --git a/ext/intl/tests/collator_create4.phpt b/ext/intl/tests/collator_create.phpt similarity index 70% rename from ext/intl/tests/collator_create4.phpt rename to ext/intl/tests/collator_create.phpt index 5747d366dcfa4..2554571ba355f 100644 --- a/ext/intl/tests/collator_create4.phpt +++ b/ext/intl/tests/collator_create.phpt @@ -1,5 +1,5 @@ --TEST-- -create() icu >= 53.1 +Collator creation tests --EXTENSIONS-- intl --FILE-- @@ -17,11 +17,9 @@ function ut_main() $locales = array( 'EN-US-ODESSA', 'UK_UA_ODESSA', - 'uk-ua_CALIFORNIA@currency=;currency=GRN', '', 'root', 'uk@currency=EURO', - '12345678911131517192123252729313335373941434547495153575961636567697173757779818385878991939597991234567891113151719212325272931333537394143454749515357596163656769717375777981838587899193959799' ); foreach( $locales as $locale ) @@ -62,7 +60,6 @@ Locale: 'UK_UA_ODESSA' ULOC_REQUESTED_LOCALE = 'UK_UA_ODESSA' ULOC_VALID_LOCALE = 'uk' ULOC_ACTUAL_LOCALE = 'uk' -Error creating collator with 'uk-ua_CALIFORNIA@currency=;currency=GRN' locale: collator_create: unable to open ICU collator: U_ILLEGAL_ARGUMENT_ERROR Locale: '' ULOC_REQUESTED_LOCALE = '' ULOC_VALID_LOCALE = '%s' @@ -75,4 +72,3 @@ Locale: 'uk@currency=EURO' ULOC_REQUESTED_LOCALE = 'uk@currency=EURO' ULOC_VALID_LOCALE = 'uk' ULOC_ACTUAL_LOCALE = 'uk' -Error creating collator with '12345678911131517192123252729313335373941434547495153575961636567697173757779818385878991939597991234567891113151719212325272931333537394143454749515357596163656769717375777981838587899193959799' locale: Locale string too long, should be no longer than %d characters: U_ILLEGAL_ARGUMENT_ERROR diff --git a/ext/intl/tests/collator_create_errors.phpt b/ext/intl/tests/collator_create_errors.phpt new file mode 100644 index 0000000000000..41fc794f67c17 --- /dev/null +++ b/ext/intl/tests/collator_create_errors.phpt @@ -0,0 +1,40 @@ +--TEST-- +Collator creation errors +--EXTENSIONS-- +intl +--FILE-- +getMessage(), PHP_EOL; + } + + $c = Collator::create($locale); + var_dump($c); + var_dump(intl_get_error_message()); + + $c = collator_create($locale); + var_dump($c); + var_dump(intl_get_error_message()); +} + +?> +--EXPECT-- +IntlException: Collator::__construct(): unable to open ICU collator +NULL +string(73) "Collator::create(): unable to open ICU collator: U_ILLEGAL_ARGUMENT_ERROR" +NULL +string(72) "collator_create(): unable to open ICU collator: U_ILLEGAL_ARGUMENT_ERROR" +IntlException: Collator::__construct(): Locale string too long, should be no longer than 156 characters +NULL +string(109) "Collator::create(): Locale string too long, should be no longer than 156 characters: U_ILLEGAL_ARGUMENT_ERROR" +NULL +string(108) "collator_create(): Locale string too long, should be no longer than 156 characters: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/collation_customization.phpt b/ext/intl/tests/collator_customization.phpt similarity index 90% rename from ext/intl/tests/collation_customization.phpt rename to ext/intl/tests/collator_customization.phpt index aeb14386fd217..befb2c129e2c2 100644 --- a/ext/intl/tests/collation_customization.phpt +++ b/ext/intl/tests/collator_customization.phpt @@ -6,11 +6,10 @@ intl ---EXPECT-- -U_ZERO_ERROR -Error getting attribute value: U_ILLEGAL_ARGUMENT_ERROR diff --git a/ext/intl/tests/collator_get_invalid_attribute.phpt b/ext/intl/tests/collator_get_invalid_attribute.phpt new file mode 100644 index 0000000000000..11a1e0ef9b646 --- /dev/null +++ b/ext/intl/tests/collator_get_invalid_attribute.phpt @@ -0,0 +1,23 @@ +--TEST-- +Collator get invalid attribute +--EXTENSIONS-- +intl +--FILE-- +getAttribute($attr)); +var_dump($coll->getErrorMessage()); + +var_dump(collator_get_attribute($coll, $attr)); +var_dump(collator_get_error_message($coll)); + +?> +--EXPECT-- +bool(false) +string(81) "Collator::getAttribute(): Error getting attribute value: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(81) "collator_get_attribute(): Error getting attribute value: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/cpbi_clone_equality.phpt b/ext/intl/tests/cpbi_clone_equality.phpt index 37f1998e257a9..caea9f8ba08b0 100644 --- a/ext/intl/tests/cpbi_clone_equality.phpt +++ b/ext/intl/tests/cpbi_clone_equality.phpt @@ -2,10 +2,10 @@ IntlCodePointBreakIterator: clone and equality --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT --FILE-- getMessage() . " in " . $e->getFile() . " on line " . $e->getLine() . "\n"; -} try { var_dump(new IntlDateFormatter(NULL, 0, 0, 'bad timezone')); -} catch (IntlException $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; } try { var_dump(new IntlDateFormatter(NULL, 0, 0, NULL, 3)); -} catch (IntlException $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; } try { var_dump(new IntlDateFormatter(NULL, 0, 0, NULL, new stdclass)); -} catch (TypeError $e) { - print_exception($e); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; } ?> ---EXPECTF-- - -Exception: datefmt_create: No such time zone: 'bad timezone' in %s on line %d - -Exception: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %s on line %d +--EXPECT-- +IntlException: IntlDateFormatter::__construct(): No such time zone: "bad timezone" +IntlException: IntlDateFormatter::__construct(): Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object +TypeError: IntlDateFormatter::__construct(): Argument #5 ($calendar) must be of type IntlCalendar|int|null, stdClass given -Exception: IntlDateFormatter::__construct(): Argument #5 ($calendar) must be of type IntlCalendar|int|null, stdClass given in %s on line %d diff --git a/ext/intl/tests/dateformat_bug68893.phpt b/ext/intl/tests/dateformat_bug68893.phpt index 341acd49a6db4..b0510097fc501 100644 --- a/ext/intl/tests/dateformat_bug68893.phpt +++ b/ext/intl/tests/dateformat_bug68893.phpt @@ -14,6 +14,6 @@ var_dump($f, intl_get_error_message()); ?> --EXPECT-- NULL -string(67) "datefmt_create: invalid date format style: U_ILLEGAL_ARGUMENT_ERROR" +string(69) "datefmt_create(): invalid date format style: U_ILLEGAL_ARGUMENT_ERROR" NULL -string(67) "datefmt_create: invalid time format style: U_ILLEGAL_ARGUMENT_ERROR" +string(69) "datefmt_create(): invalid time format style: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/dateformat_calendars_variant3.phpt b/ext/intl/tests/dateformat_calendars_variant.phpt similarity index 60% rename from ext/intl/tests/dateformat_calendars_variant3.phpt rename to ext/intl/tests/dateformat_calendars_variant.phpt index 037d8066a0815..48c44c58834a4 100644 --- a/ext/intl/tests/dateformat_calendars_variant3.phpt +++ b/ext/intl/tests/dateformat_calendars_variant.phpt @@ -8,7 +8,6 @@ intl = 0) die('skip for ICU < 72.1'); ?> --FILE-- format(strtotime('2012-01-01 00:00:00 +0000'))); var_dump($fmt2->format(strtotime('2012-01-01 00:00:00 +0000'))); var_dump($fmt3->format(strtotime('2012-01-01 00:00:00 +0000'))); -new IntlDateFormatter('en_US@calendar=hebrew', - IntlDateFormatter::FULL, - IntlDateFormatter::FULL, - 'GMT+05:12', - -1); ?> -==DONE== ---EXPECTF-- +--EXPECT-- string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" string(44) "Sunday, 6 Tevet 5772 at 5:12:00 AM GMT+05:12" - -Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %sdateformat_calendars_variant3.php:%d -Stack trace: -#0 %sdateformat_calendars_variant3.php(%d): IntlDateFormatter->__construct('en_US@calendar=...', 0, 0, 'GMT+05:12', -1) -#1 {main} - thrown %sdateformat_calendars_variant3.php on line %d diff --git a/ext/intl/tests/dateformat_calendars_variant_icu72-1.phpt b/ext/intl/tests/dateformat_calendars_variant_icu72-1.phpt index c63b302d8e5e9..d5d0f437d9b64 100644 --- a/ext/intl/tests/dateformat_calendars_variant_icu72-1.phpt +++ b/ext/intl/tests/dateformat_calendars_variant_icu72-1.phpt @@ -8,7 +8,6 @@ intl = 72.1'); ?> --FILE-- format(strtotime('2012-01-01 00:00:00 +0000'))); var_dump($fmt2->format(strtotime('2012-01-01 00:00:00 +0000'))); var_dump($fmt3->format(strtotime('2012-01-01 00:00:00 +0000'))); -new IntlDateFormatter('en_US@calendar=hebrew', - IntlDateFormatter::FULL, - IntlDateFormatter::FULL, - 'GMT+05:12', - -1); ?> -==DONE== ---EXPECTF-- +--EXPECT-- string(49) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" string(49) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12" string(46) "Sunday, 6 Tevet 5772 at 5:12:00 AM GMT+05:12" - -Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %s:%d -Stack trace: -#0 %s(%d): IntlDateFormatter->__construct('en_US@calendar=...', 0, 0, 'GMT+05:12', -1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/dateformat_create_cal_arg_variant4.phpt b/ext/intl/tests/dateformat_create_cal_arg_variant4.phpt index 1571e08740edd..ad09a60327d7a 100644 --- a/ext/intl/tests/dateformat_create_cal_arg_variant4.phpt +++ b/ext/intl/tests/dateformat_create_cal_arg_variant4.phpt @@ -2,13 +2,13 @@ IntlDateFormatter: several forms of the calendar arg --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT +date.timezone=Atlantic/Azores --SKIPIF-- = 0) die('skip for ICU < 58.1'); ?> --FILE-- = 58.1'); ?> --FILE-- getMessage(), PHP_EOL; +} + +$df = IntlDateFormatter::create($locale, $type, $type, $timezone, $invalidCalendar); +var_dump($df); +var_dump(intl_get_error_message()); + +$df = datefmt_create($locale, $type, $type, $timezone, $invalidCalendar); +var_dump($df); +var_dump(intl_get_error_message()); + +?> +--EXPECT-- +IntlException: IntlDateFormatter::__construct(): Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object +NULL +string(245) "IntlDateFormatter::create(): Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object: U_ILLEGAL_ARGUMENT_ERROR" +NULL +string(234) "datefmt_create(): Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt b/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt index 096d04bbb514d..d9a506a1dc413 100644 --- a/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt +++ b/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt @@ -2,13 +2,13 @@ IntlDateFormatter::formatObject(): IntlCalendar tests --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT +date.timezone=Europe/Lisbon --SKIPIF-- = 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> --FILE-- = 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> --FILE-- getMessage(), "\n"; + var_dump(intl_get_error_message()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; } -$cal = IntlCalendar::createInstance(); +var_dump(IntlDateFormatter::formatObject(new stdclass)); +var_dump(intl_get_error_message()); +var_dump(IntlDateFormatter::formatObject(new A)); +var_dump(intl_get_error_message()); + var_dump(IntlDateFormatter::formatObject($cal, -2)); +var_dump(intl_get_error_message()); var_dump(IntlDateFormatter::formatObject($cal, array())); +var_dump(intl_get_error_message()); var_dump(IntlDateFormatter::formatObject($cal, array(1,2,3))); +var_dump(intl_get_error_message()); var_dump(IntlDateFormatter::formatObject($cal, array(array(), 1))); +var_dump(intl_get_error_message()); var_dump(IntlDateFormatter::formatObject($cal, array(1, -2))); +var_dump(intl_get_error_message()); var_dump(IntlDateFormatter::formatObject($cal, "")); +var_dump(intl_get_error_message()); ?> ---EXPECTF-- -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the passed object must be an instance of either IntlCalendar or DateTimeInterface in %s on line %d +--EXPECT-- +DateObjectError: Object of type B (inheriting DateTime) has not been correctly initialized by calling parent::__construct() in its constructor bool(false) - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad IntlCalendar instance: not initialized properly in %s on line %d +string(130) "IntlDateFormatter::formatObject(): the passed object must be an instance of either IntlCalendar or DateTimeInterface: U_ZERO_ERROR" bool(false) -Object of type B (inheriting DateTime) has not been correctly initialized by calling parent::__construct() in its constructor - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the date/time format type is invalid in %s on line %d +string(112) "IntlDateFormatter::formatObject(): bad IntlCalendar instance: not initialized properly: U_ILLEGAL_ARGUMENT_ERROR" bool(false) - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; if array, it must have two elements in %s on line %d +string(97) "IntlDateFormatter::formatObject(): the date/time format type is invalid: U_ILLEGAL_ARGUMENT_ERROR" bool(false) - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; if array, it must have two elements in %s on line %d +string(108) "IntlDateFormatter::formatObject(): bad format; if array, it must have two elements: U_ILLEGAL_ARGUMENT_ERROR" bool(false) - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; the date format (first element of the array) is not valid in %s on line %d +string(108) "IntlDateFormatter::formatObject(): bad format; if array, it must have two elements: U_ILLEGAL_ARGUMENT_ERROR" bool(false) - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; the time format (second element of the array) is not valid in %s on line %d +string(130) "IntlDateFormatter::formatObject(): bad format; the date format (first element of the array) is not valid: U_ILLEGAL_ARGUMENT_ERROR" bool(false) - -Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the format is empty in %s on line %d +string(131) "IntlDateFormatter::formatObject(): bad format; the time format (second element of the array) is not valid: U_ILLEGAL_ARGUMENT_ERROR" bool(false) +string(80) "IntlDateFormatter::formatObject(): the format is empty: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/dateformat_format_error.phpt b/ext/intl/tests/dateformat_format_error.phpt new file mode 100644 index 0000000000000..4358271efd08c --- /dev/null +++ b/ext/intl/tests/dateformat_format_error.phpt @@ -0,0 +1,26 @@ +--TEST-- +IntlDateFormatter->format() errors +--EXTENSIONS-- +intl +--FILE-- +format($object); +var_dump($v); +var_dump(intl_get_error_message()); + +$v = datefmt_format($f, $object); +var_dump($v); +var_dump(intl_get_error_message()); + +?> +--EXPECT-- +bool(false) +string(140) "IntlDateFormatter::format(): invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(129) "datefmt_format(): invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/dateformat_format_relative.phpt b/ext/intl/tests/dateformat_format_relative.phpt index c93c1fd4a332b..6455264142a60 100644 --- a/ext/intl/tests/dateformat_format_relative.phpt +++ b/ext/intl/tests/dateformat_format_relative.phpt @@ -2,11 +2,11 @@ datefmt_format_code() with relative formats --EXTENSIONS-- intl +--INI +date.timezone=America/Los_Angeles --FILE-- setTimezone(new DateTimeZone("PDT")); - $dates = array( - $d1, - $d2, - new StdClass(), - ); //Test format with input as a timestamp : integer foreach( $time_arr as $timestamp_entry){ $res_str .= "\n------------\n"; $res_str .= "\nInput timestamp is : $timestamp_entry"; $res_str .= "\n------------\n"; - foreach( $locale_arr as $locale_entry ){ - foreach( $datetype_arr as $datetype_entry ) + foreach( $datetype_arr as $datetype_entry ) { $res_str .= "\nIntlDateFormatter locale= $locale_entry ,datetype = $datetype_entry ,timetype =$datetype_entry "; $fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry, $timezone, IntlDateFormatter::GREGORIAN); @@ -98,19 +88,17 @@ function ut_main() $res_str .= "\nFormatted timestamp is : $formatted"; } } - } //Test format with input as a localtime :array foreach( $localtime_arr as $localtime_entry){ $res_str .= "\n------------\n"; $res_str .= "\nInput localtime is : "; foreach( $localtime_entry as $key => $value){ - $res_str .= "$key : '$value' , "; + $res_str .= "$key : '$value' , "; } $res_str .= "\n------------\n"; - foreach( $locale_arr as $locale_entry ){ - foreach( $datetype_arr as $datetype_entry ) + foreach( $datetype_arr as $datetype_entry ) { $res_str .= "\nIntlDateFormatter locale= $locale_entry ,datetype = $datetype_entry ,timetype =$datetype_entry "; $fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry, $timezone, IntlDateFormatter::GREGORIAN ); @@ -122,22 +110,23 @@ function ut_main() } } } - } + $dates = array( + $d1, + $d2, + ); foreach($dates as $date_entry) { - foreach( $locale_arr as $locale_entry ){ - foreach( $datetype_arr as $datetype_entry ) { - $res_str .= "\n------------"; - $res_str .= "\nDate is: ".var_export($date_entry, true); - $res_str .= "\n------------"; - - $fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry, $timezone, IntlDateFormatter::GREGORIAN ); - $formatted1 = ut_datefmt_format( $fmt , $date_entry); - if( intl_get_error_code() == U_ZERO_ERROR){ - $res_str .= "\nFormatted DateTime is : $formatted1"; - }else{ - $res_str .= "\nError while formatting as: '".intl_get_error_message()."'"; - } + foreach( $datetype_arr as $datetype_entry ) { + $res_str .= "\n------------"; + $res_str .= "\nDate is: ".var_export($date_entry, true); + $res_str .= "\n------------"; + + $fmt = ut_datefmt_create( $locale_entry , $datetype_entry ,$datetype_entry, $timezone, IntlDateFormatter::GREGORIAN ); + $formatted1 = ut_datefmt_format( $fmt , $date_entry); + if( intl_get_error_code() == U_ZERO_ERROR){ + $res_str .= "\nFormatted DateTime is : $formatted1"; + }else{ + $res_str .= "\nError while formatting as: '".intl_get_error_message()."'"; } } } @@ -397,28 +386,3 @@ Date is: \DateTime::__set_state(array( )) ------------ Formatted DateTime is : 20001230 05:04 PM ------------- -Date is: (object) array( -) ------------- -Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------- -Date is: (object) array( -) ------------- -Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------- -Date is: (object) array( -) ------------- -Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------- -Date is: (object) array( -) ------------- -Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------- -Date is: (object) array( -) ------------- -Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' diff --git a/ext/intl/tests/dateformat_get_set_calendar_variant4.phpt b/ext/intl/tests/dateformat_get_set_calendar_variant4.phpt index 6842cdf1c4084..4484bd4647a16 100644 --- a/ext/intl/tests/dateformat_get_set_calendar_variant4.phpt +++ b/ext/intl/tests/dateformat_get_set_calendar_variant4.phpt @@ -2,13 +2,13 @@ IntlDateFormatter: setCalendar()/getCalendar()/getCalendarObject() --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT +date.timezone=Atlantic/Azores --SKIPIF-- = 0) die('skip for ICU < 58.1'); ?> --FILE-- = 58.1 and < 70.1 --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT +date.timezone=Atlantic/Azores --SKIPIF-- = 0) die('skip for ICU >= 58.1 and < 70.1'); ?> --FILE-- = 70.1 --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT +date.timezone=Atlantic/Azores --SKIPIF-- = 70.1'); ?> --FILE-- getMessage(); -} -?> ---EXPECTF-- -Warning: PHP Startup: Invalid date.timezone value 'Mars/Utopia_Planitia', using 'UTC' instead in %s on line %d -Wat? diff --git a/ext/intl/tests/dateformat_setTimeZone_error.phpt b/ext/intl/tests/dateformat_setTimeZone_error.phpt index b911c4b41ec0c..08ed8876d2f7e 100644 --- a/ext/intl/tests/dateformat_setTimeZone_error.phpt +++ b/ext/intl/tests/dateformat_setTimeZone_error.phpt @@ -2,27 +2,26 @@ IntlDateFormatter::setTimeZone() bad args --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT +date.timezone=Atlantic/Azores --FILE-- setTimeZone(array()); -} catch (IntlException $e) { - echo $e->getMessage() . PHP_EOL; +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } try { $df->setTimeZone('non existing timezone'); -} catch (IntlException $e) { - echo $e->getMessage(); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } ?> ---EXPECTF-- -Warning: Array to string conversion in %s on line %d -datefmt_set_timezone: No such time zone: 'Array' -datefmt_set_timezone: No such time zone: 'non existing timezone' +--EXPECT-- +TypeError: IntlDateFormatter::setTimeZone(): Argument #1 ($timezone) must be of type object|string|null, array given +IntlException: IntlDateFormatter::setTimeZone(): No such time zone: "non existing timezone" diff --git a/ext/intl/tests/dateformat_set_timezone_id3.phpt b/ext/intl/tests/dateformat_set_timezone_id3.phpt index 16c0bb05b9be3..89e834aacdb02 100644 --- a/ext/intl/tests/dateformat_set_timezone_id3.phpt +++ b/ext/intl/tests/dateformat_set_timezone_id3.phpt @@ -9,8 +9,6 @@ intl --FILE-- true, 'America/Los_Angeles' => true, 'America/Chicago' => true, - 'CN' => false ); $timestamp_entry = 0; @@ -61,10 +58,7 @@ include_once( 'ut_common.inc' ); // Run the test ut_run(); ?> ---EXPECTF-- -datefmt_set_timezone: No such time zone: 'CN' -datefmt_set_timezone: No such time zone: 'CN' - +--EXPECT-- After creation of the dateformatter : timezone_id= US/Pacific ----------- Trying to set timezone_id= America/New_York @@ -81,8 +75,3 @@ Trying to set timezone_id= America/Chicago After call to set_timezone_id : timezone_id= America/Chicago Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 6:00:00 PM Central Standard Time Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 7:00:00 PM Central Standard Time ------------ -Trying to set timezone_id= CN -After call to set_timezone_id : timezone_id= America/Chicago -Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 6:00:00 PM Central Standard Time -Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 7:00:00 PM Central Standard Time diff --git a/ext/intl/tests/dateformat_set_timezone_id_icu72-1.phpt b/ext/intl/tests/dateformat_set_timezone_id_icu72-1.phpt index eebc6f0973a05..6424ba1e6b40e 100644 --- a/ext/intl/tests/dateformat_set_timezone_id_icu72-1.phpt +++ b/ext/intl/tests/dateformat_set_timezone_id_icu72-1.phpt @@ -1,5 +1,5 @@ --TEST-- -datefmt_set_timezone_id_code() icu >= 4.8 +datefmt_set_timezone_id_code() icu >= 72.1 --INI-- date.timezone=Atlantic/Azores --EXTENSIONS-- @@ -9,8 +9,6 @@ intl --FILE-- true, 'America/Los_Angeles' => true, 'America/Chicago' => true, - 'CN' => false ); $timestamp_entry = 0; @@ -61,10 +58,7 @@ include_once( 'ut_common.inc' ); // Run the test ut_run(); ?> ---EXPECTF-- -datefmt_set_timezone: No such time zone: 'CN' -datefmt_set_timezone: No such time zone: 'CN' - +--EXPECT-- After creation of the dateformatter : timezone_id= US/Pacific ----------- Trying to set timezone_id= America/New_York @@ -81,8 +75,3 @@ Trying to set timezone_id= America/Chicago After call to set_timezone_id : timezone_id= America/Chicago Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 6:00:00 PM Central Standard Time Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 7:00:00 PM Central Standard Time ------------ -Trying to set timezone_id= CN -After call to set_timezone_id : timezone_id= America/Chicago -Formatting timestamp=0 resulted in Wednesday, December 31, 1969 at 6:00:00 PM Central Standard Time -Formatting timestamp=3600 resulted in Wednesday, December 31, 1969 at 7:00:00 PM Central Standard Time diff --git a/ext/intl/tests/dateformat_timezone_arg_variations4.phpt b/ext/intl/tests/dateformat_timezone_arg_variations4.phpt index 0c2ea02a56d48..2abdc34a2ac86 100644 --- a/ext/intl/tests/dateformat_timezone_arg_variations4.phpt +++ b/ext/intl/tests/dateformat_timezone_arg_variations4.phpt @@ -2,10 +2,10 @@ IntlDateFormatter: several forms of the timezone arg --EXTENSIONS-- intl +--INI-- +date.timezone=Atlantic/Azores --FILE-- getBestPattern("YYYYMMMddjjmm"), "\n"; diff --git a/ext/intl/tests/datepatterngenerator_error.phpt b/ext/intl/tests/datepatterngenerator_error.phpt index 93419899482f7..6ff0e19263f01 100644 --- a/ext/intl/tests/datepatterngenerator_error.phpt +++ b/ext/intl/tests/datepatterngenerator_error.phpt @@ -4,12 +4,12 @@ IntlDatePatternGenerator::getBestPattern(): errors intl --FILE-- getBestPattern("jjmm\x80")); +var_dump(intl_get_error_message()); ?> ---EXPECTF-- -Warning: IntlDatePatternGenerator::getBestPattern(): Skeleton is not a valid UTF-8 string in %s on line %d +--EXPECT-- bool(false) +string(102) "IntlDatePatternGenerator::getBestPattern(): Skeleton is not a valid UTF-8 string: U_INVALID_CHAR_FOUND" diff --git a/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt b/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt index 279554123b795..e67c1be2f1b4e 100644 --- a/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt +++ b/ext/intl/tests/datepatterngenerator_get_best_pattern.phpt @@ -2,14 +2,13 @@ IntlDatePatternGenerator::getBestPattern() --EXTENSIONS-- intl +--INI-- +intl.default_locale=en_US --SKIPIF-- = 0) die('skip for ICU < 72.1'); ?> --FILE-- getBestPattern("YYYYMMMdd"), "\n"; echo $dtpg->getBestPattern(""), "\n"; -try { - $dtpg->getBestPattern(); -} catch(\ArgumentCountError $e) { - echo $e->getMessage(), "\n"; -} - ?> --EXPECT-- h:mm a HH:mm MMM dd, YYYY dd. MMM YYYY - -IntlDatePatternGenerator::getBestPattern() expects exactly 1 argument, 0 given diff --git a/ext/intl/tests/datepatterngenerator_get_best_pattern_icu72-1.phpt b/ext/intl/tests/datepatterngenerator_get_best_pattern_icu72-1.phpt index 2f4f744757caf..c35b2ff8d4847 100644 --- a/ext/intl/tests/datepatterngenerator_get_best_pattern_icu72-1.phpt +++ b/ext/intl/tests/datepatterngenerator_get_best_pattern_icu72-1.phpt @@ -2,14 +2,13 @@ IntlDatePatternGenerator::getBestPattern() --EXTENSIONS-- intl +--INI-- +intl.default_locale=en_US --SKIPIF-- = 72.1'); ?> --FILE-- getBestPattern("YYYYMMMdd"), "\n"; echo $dtpg->getBestPattern(""), "\n"; -try { - $dtpg->getBestPattern(); -} catch(\ArgumentCountError $e) { - echo $e->getMessage(), "\n"; -} - ?> --EXPECT-- h:mm a HH:mm MMM dd, YYYY dd. MMM YYYY - -IntlDatePatternGenerator::getBestPattern() expects exactly 1 argument, 0 given diff --git a/ext/intl/tests/deprecated_U_MULTIPLE_DECIMAL_SEPERATORS.phpt b/ext/intl/tests/deprecated_U_MULTIPLE_DECIMAL_SEPERATORS.phpt new file mode 100644 index 0000000000000..33cdbda7d2296 --- /dev/null +++ b/ext/intl/tests/deprecated_U_MULTIPLE_DECIMAL_SEPERATORS.phpt @@ -0,0 +1,15 @@ +--TEST-- +U_MULTIPLE_DECIMAL_SEPERATORS is deprecated +--EXTENSIONS-- +intl +--FILE-- + +--EXPECTF-- +Deprecated: Constant U_MULTIPLE_DECIMAL_SEPERATORS is deprecated since 8.3, use U_MULTIPLE_DECIMAL_SEPARATORS instead in %s on line %d +int(65793) + +Deprecated: Constant U_MULTIPLE_DECIMAL_SEPERATORS is deprecated since 8.3, use U_MULTIPLE_DECIMAL_SEPARATORS instead in %s on line %d +int(65793) diff --git a/ext/intl/tests/formatter/rounding_modes.phpt b/ext/intl/tests/formatter/rounding_modes.phpt index 3261e3740795e..bcb32983959a8 100644 --- a/ext/intl/tests/formatter/rounding_modes.phpt +++ b/ext/intl/tests/formatter/rounding_modes.phpt @@ -6,7 +6,6 @@ intl = 69.0'); ?> --FILE-- getMessage() - . " in " . $e->getFile() . " on line " . $e->getLine() . "\n"; + echo "\n", $e::class, ": ", $e->getMessage(), "\n"; } function crt($t, $l, $s) { @@ -62,14 +61,14 @@ try { err($fmt); try { $fmt = numfmt_create(); -} catch (TypeError $e) { +} catch (Throwable $e) { print_exception($e); $fmt = null; } err($fmt); try { $fmt = NumberFormatter::create(); -} catch (TypeError $e) { +} catch (Throwable $e) { print_exception($e); $fmt = null; } @@ -78,7 +77,7 @@ err($fmt); $fmt = new NumberFormatter('en_US', NumberFormatter::DECIMAL); try { $fmt->__construct('en_US', NumberFormatter::DECIMAL); -} catch (Error $e) { +} catch (Throwable $e) { print_exception($e); $fmt = null; } @@ -95,16 +94,16 @@ foreach($args as $arg) { ?> --EXPECTF-- -ArgumentCountError: NumberFormatter::__construct() expects at least 2 arguments, 0 given in %s on line %d +ArgumentCountError: NumberFormatter::__construct() expects at least 2 arguments, 0 given 'U_ZERO_ERROR' -ArgumentCountError: numfmt_create() expects at least 2 arguments, 0 given in %s on line %d +ArgumentCountError: numfmt_create() expects at least 2 arguments, 0 given 'U_ZERO_ERROR' -ArgumentCountError: NumberFormatter::create() expects at least 2 arguments, 0 given in %s on line %d +ArgumentCountError: NumberFormatter::create() expects at least 2 arguments, 0 given 'U_ZERO_ERROR' -Error: NumberFormatter object is already constructed in %s on line %d +Error: NumberFormatter object is already constructed 'U_ZERO_ERROR' Deprecated: NumberFormatter::__construct(): Passing null to parameter #1 ($locale) of type string is deprecated in %s on line %d @@ -119,30 +118,30 @@ Deprecated: numfmt_create(): Passing null to parameter #1 ($locale) of type stri Deprecated: numfmt_create(): Passing null to parameter #2 ($style) of type int is deprecated in %s on line %d -ValueError: NumberFormatter::__construct(): Argument #1 ($locale) "%s" is invalid in %s on line %d +ValueError: NumberFormatter::__construct(): Argument #1 ($locale) "whatever" is invalid 'U_ZERO_ERROR' -ValueError: NumberFormatter::create(): Argument #1 ($locale) "%s" is invalid in %s on line %d +ValueError: NumberFormatter::create(): Argument #1 ($locale) "whatever" is invalid 'U_ZERO_ERROR' -ValueError: numfmt_create(): Argument #1 ($locale) "%s" is invalid in %s on line %d +ValueError: numfmt_create(): Argument #1 ($locale) "whatever" is invalid 'U_ZERO_ERROR' -TypeError: NumberFormatter::__construct(): Argument #1 ($locale) must be of type string, array given in %s on line %d +TypeError: NumberFormatter::__construct(): Argument #1 ($locale) must be of type string, array given 'U_ZERO_ERROR' -TypeError: NumberFormatter::create(): Argument #1 ($locale) must be of type string, array given in %s on line %d +TypeError: NumberFormatter::create(): Argument #1 ($locale) must be of type string, array given 'U_ZERO_ERROR' -TypeError: numfmt_create(): Argument #1 ($locale) must be of type string, array given in %s on line %d +TypeError: numfmt_create(): Argument #1 ($locale) must be of type string, array given 'U_ZERO_ERROR' -IntlException: Constructor failed in %s on line %d -'numfmt_create: number formatter creation failed: U_UNSUPPORTED_ERROR' -'numfmt_create: number formatter creation failed: U_UNSUPPORTED_ERROR' -'numfmt_create: number formatter creation failed: U_UNSUPPORTED_ERROR' +IntlException: NumberFormatter::__construct(): number formatter creation failed +'NumberFormatter::__construct(): number formatter creation failed: U_UNSUPPORTED_ERROR' +'NumberFormatter::create(): number formatter creation failed: U_UNSUPPORTED_ERROR' +'numfmt_create(): number formatter creation failed: U_UNSUPPORTED_ERROR' -IntlException: Constructor failed in %s on line %d -'numfmt_create: number formatter creation failed: U_MEMORY_ALLOCATION_ERROR' -'numfmt_create: number formatter creation failed: U_MEMORY_ALLOCATION_ERROR' -'numfmt_create: number formatter creation failed: U_MEMORY_ALLOCATION_ERROR' +IntlException: NumberFormatter::__construct(): number formatter creation failed +'NumberFormatter::__construct(): number formatter creation failed: U_MEMORY_ALLOCATION_ERROR' +'NumberFormatter::create(): number formatter creation failed: U_MEMORY_ALLOCATION_ERROR' +'numfmt_create(): number formatter creation failed: U_MEMORY_ALLOCATION_ERROR' diff --git a/ext/intl/tests/formatter_get_error.phpt b/ext/intl/tests/formatter_get_error.phpt index b8f1269fc65f9..16a1c1db47662 100644 --- a/ext/intl/tests/formatter_get_error.phpt +++ b/ext/intl/tests/formatter_get_error.phpt @@ -5,27 +5,43 @@ intl --FILE-- parseCurrency('123.45', $currency); +var_dump($currency); +var_dump($nf->getErrorMessage()); +var_dump($nf->getErrorCode()); +$pos = 0; +$nf->parseCurrency('123.45', $currency, $pos); +var_dump($currency); +var_dump($nf->getErrorMessage()); +var_dump($nf->getErrorCode()); -function ut_main() -{ - $fmt = ut_nfmt_create( "en_US", NumberFormatter::CURRENCY ); - $currency = ''; - $pos = 0; - $num = ut_nfmt_parse_currency( $fmt, '123.45', $currency, $pos ); - if( $num === false ) - return $fmt->getErrorMessage() . " (" . $fmt->getErrorCode() . ")\n"; - else - return "Ooops, an error should have occurred."; -} +$nf = numfmt_create("en_US", NumberFormatter::CURRENCY); +var_dump(numfmt_parse_currency($nf, '123.45', $currency)); +var_dump($currency); +var_dump($nf->getErrorMessage()); +var_dump($nf->getErrorCode()); -include_once( 'ut_common.inc' ); +$pos = 0; +var_dump(numfmt_parse_currency($nf, '123.45', $currency, $pos)); +var_dump($currency); +var_dump($nf->getErrorMessage()); +var_dump($nf->getErrorCode()); -// Run the test -ut_run(); ?> --EXPECT-- -Number parsing failed: U_PARSE_ERROR (9) +NULL +string(70) "NumberFormatter::parseCurrency(): Number parsing failed: U_PARSE_ERROR" +int(9) +NULL +string(70) "NumberFormatter::parseCurrency(): Number parsing failed: U_PARSE_ERROR" +int(9) +bool(false) +NULL +string(61) "numfmt_parse_currency(): Number parsing failed: U_PARSE_ERROR" +int(9) +bool(false) +NULL +string(61) "numfmt_parse_currency(): Number parsing failed: U_PARSE_ERROR" +int(9) diff --git a/ext/intl/tests/formatter_get_set_pattern2.phpt b/ext/intl/tests/formatter_get_set_pattern2.phpt index 0d3e3e87d72dd..7b454ae965eac 100644 --- a/ext/intl/tests/formatter_get_set_pattern2.phpt +++ b/ext/intl/tests/formatter_get_set_pattern2.phpt @@ -37,10 +37,6 @@ function ut_main() ut_nfmt_set_pattern($fmt, str_repeat('@', 200)); $res_str .= "New pattern: '" . ut_nfmt_get_pattern( $fmt ) . "'\n"; $res_str .= "Formatted number: " . ut_nfmt_format( $fmt, $test_value ) . "\n"; - $res = ut_nfmt_set_pattern( $fmt, "0.0 .#.#.#"); - if ($res !== false) - die("ut_nfmt_set_pattern should have failed"); - $res_str .= ut_nfmt_get_error_message( $fmt ) . " (" . ut_nfmt_get_error_code( $fmt ) . ")\n"; return $res_str; } @@ -56,4 +52,3 @@ New pattern: '0.0' Formatted number: 12345.1 New pattern: '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@' Formatted number: 12345.123456000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Error setting pattern value at line 0, offset 0: U_UNQUOTED_SPECIAL (65555) diff --git a/ext/intl/tests/formatter_set_invalid_pattern.phpt b/ext/intl/tests/formatter_set_invalid_pattern.phpt new file mode 100644 index 0000000000000..2e94719e7568b --- /dev/null +++ b/ext/intl/tests/formatter_set_invalid_pattern.phpt @@ -0,0 +1,21 @@ +--TEST-- +numfmt_set_pattern() with invalid pattern +--EXTENSIONS-- +intl +--FILE-- +setPattern($pattern)); +var_dump($fmt->getErrorMessage()); +var_dump(numfmt_set_pattern($fmt, $pattern)); +var_dump(numfmt_get_error_message($fmt)); + +?> +--EXPECT-- +bool(false) +string(98) "NumberFormatter::setPattern(): Error setting pattern value at line 0, offset 0: U_UNQUOTED_SPECIAL" +bool(false) +string(89) "numfmt_set_pattern(): Error setting pattern value at line 0, offset 0: U_UNQUOTED_SPECIAL" diff --git a/ext/intl/tests/gh11658.phpt b/ext/intl/tests/gh11658.phpt index f0cfab9280ef6..da3cc8b9a1c88 100644 --- a/ext/intl/tests/gh11658.phpt +++ b/ext/intl/tests/gh11658.phpt @@ -5,17 +5,17 @@ intl --FILE-- ---EXPECTF-- -Warning: MessageFormatter::formatMessage(): pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}") in %s on line %d +--EXPECT-- bool(false) - -Warning: msgfmt_format_message(): pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}") in %s on line %d +MessageFormatter::formatMessage(): pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}"): U_PATTERN_SYNTAX_ERROR bool(false) +msgfmt_format_message(): pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}"): U_PATTERN_SYNTAX_ERROR diff --git a/ext/intl/tests/gh11942_datefmt_locale_canonicalization.phpt b/ext/intl/tests/gh11942_datefmt_locale_canonicalization.phpt new file mode 100644 index 0000000000000..26b0234fd3bdf --- /dev/null +++ b/ext/intl/tests/gh11942_datefmt_locale_canonicalization.phpt @@ -0,0 +1,37 @@ +--TEST-- +GH-11942 (IntlDateFormatter should canonicalize locale strings) +--EXTENSIONS-- +intl +--FILE-- +getLocale(); + + $status = ($actual === $expected) ? 'PASS' : 'FAIL'; + echo "Input: $input -> Expected: $expected -> Actual: $actual -> $status\n"; +} + +$dateFormatter = new IntlDateFormatter('pt_PT.utf8', IntlDateFormatter::SHORT, IntlDateFormatter::NONE, 'UTC'); +$dateResult = $dateFormatter->format(1691585260); +echo "\nDateFormatter with pt_PT.utf8: " . $dateResult . "\n"; +?> +--EXPECT-- +Testing IntlDateFormatter locale canonicalization: +Input: pt -> Expected: pt -> Actual: pt -> PASS +Input: pt-PT -> Expected: pt_PT -> Actual: pt_PT -> PASS +Input: pt_PT.utf8 -> Expected: pt_PT -> Actual: pt_PT -> PASS +Input: fr_CA@euro -> Expected: fr_CA -> Actual: fr_CA -> PASS + +DateFormatter with pt_PT.utf8: 09/08/23 diff --git a/ext/intl/tests/gh11942_numfmt_locale_canonicalization.phpt b/ext/intl/tests/gh11942_numfmt_locale_canonicalization.phpt new file mode 100644 index 0000000000000..bdb753d6127bf --- /dev/null +++ b/ext/intl/tests/gh11942_numfmt_locale_canonicalization.phpt @@ -0,0 +1,37 @@ +--TEST-- +GH-11942 (NumberFormatter should canonicalize locale strings) +--EXTENSIONS-- +intl +--FILE-- +getLocale(); + + $status = ($actual === $expected) ? 'PASS' : 'FAIL'; + echo "Input: $input -> Expected: $expected -> Actual: $actual -> $status\n"; +} + +$numFormatter = new NumberFormatter('pt_PT.utf8', NumberFormatter::DECIMAL); +$numResult = $numFormatter->format(1234.56); +echo "\nNumberFormatter with pt_PT.utf8: " . $numResult . "\n"; +?> +--EXPECT-- +Testing NumberFormatter locale canonicalization: +Input: pt -> Expected: pt -> Actual: pt -> PASS +Input: pt-PT -> Expected: pt_PT -> Actual: pt_PT -> PASS +Input: pt_PT.utf8 -> Expected: pt_PT -> Actual: pt_PT -> PASS +Input: fr_CA@euro -> Expected: fr_CA -> Actual: fr_CA -> PASS + +NumberFormatter with pt_PT.utf8: 1 234,56 diff --git a/ext/intl/tests/gh12020.phpt b/ext/intl/tests/gh12020.phpt index e4102606ca54e..c9fe55fa3cdd3 100644 --- a/ext/intl/tests/gh12020.phpt +++ b/ext/intl/tests/gh12020.phpt @@ -13,10 +13,10 @@ var_dump(msgfmt_format_message('en', 'some {wrong.format}', []), intl_get_error_ ?> --EXPECT-- bool(false) -string(128) "pattern syntax error (parse error at offset 19, after " message with {", before or at "invalid format}"): U_PATTERN_SYNTAX_ERROR" +string(163) "MessageFormatter::formatMessage(): pattern syntax error (parse error at offset 19, after " message with {", before or at "invalid format}"): U_PATTERN_SYNTAX_ERROR" bool(false) -string(116) "pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}"): U_PATTERN_SYNTAX_ERROR" +string(151) "MessageFormatter::formatMessage(): pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}"): U_PATTERN_SYNTAX_ERROR" bool(false) -string(128) "pattern syntax error (parse error at offset 19, after " message with {", before or at "invalid format}"): U_PATTERN_SYNTAX_ERROR" +string(153) "msgfmt_format_message(): pattern syntax error (parse error at offset 19, after " message with {", before or at "invalid format}"): U_PATTERN_SYNTAX_ERROR" bool(false) -string(116) "pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}"): U_PATTERN_SYNTAX_ERROR" +string(141) "msgfmt_format_message(): pattern syntax error (parse error at offset 6, after "some {", before or at "wrong.format}"): U_PATTERN_SYNTAX_ERROR" diff --git a/ext/intl/tests/gh12243.phpt b/ext/intl/tests/gh12243.phpt index cb2b177603907..786a9bd1ee8f0 100644 --- a/ext/intl/tests/gh12243.phpt +++ b/ext/intl/tests/gh12243.phpt @@ -21,4 +21,4 @@ try { ?> --EXPECT-- -datefmt_create: time format must be UDAT_PATTERN if date format is UDAT_PATTERN: U_ILLEGAL_ARGUMENT_ERROR +IntlDateFormatter::__construct(): time format must be UDAT_PATTERN if date format is UDAT_PATTERN diff --git a/ext/intl/tests/gh17469.phpt b/ext/intl/tests/gh17469.phpt index a0c5d719817d7..5a22636844227 100644 --- a/ext/intl/tests/gh17469.phpt +++ b/ext/intl/tests/gh17469.phpt @@ -1,5 +1,7 @@ --TEST-- GH-17469: UConverter::transcode() raises always E_WARNING regardless of INI settings +--EXTENSIONS-- +intl --SKIPIF-- --EXPECTF-- +Deprecated: ini_set(): Using a value different than 0 for intl.error_level is deprecated, as the intl.error_level INI setting is deprecated. Instead the intl.use_exceptions INI setting should be enabled to throw exceptions on errors or intl_get_error_code()/intl_get_error_message() should be used to manually deal with errors in %s on line %d Warning: UConverter::transcode(): Error setting encoding: 4 - U_FILE_ACCESS_ERROR in %s on line %d -Warning: UConverter::transcode(): Error setting encoding: 4 - U_FILE_ACCESS_ERROR in %s on line 5 -Error setting encoding: 4 - U_FILE_ACCESS_ERROR -Error setting encoding: 4 - U_FILE_ACCESS_ERROR +Warning: UConverter::transcode(): Error setting encoding: 4 - U_FILE_ACCESS_ERROR in %s on line %d +UConverter::transcode(): Error setting encoding: 4 - U_FILE_ACCESS_ERROR +UConverter::transcode(): Error setting encoding: 4 - U_FILE_ACCESS_ERROR diff --git a/ext/intl/tests/grapheme_empty.phpt b/ext/intl/tests/grapheme_empty.phpt index 815663342fcb0..cf2f1185abf72 100644 --- a/ext/intl/tests/grapheme_empty.phpt +++ b/ext/intl/tests/grapheme_empty.phpt @@ -5,8 +5,6 @@ intl --FILE-- getMessage() . PHP_EOL; } + +echo "--- Invalid locales ---\n"; +var_dump(grapheme_levenshtein("abc", "abc", locale: "defaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); +var_dump(intl_get_error_code()); +var_dump(intl_get_error_message()); + ?> --EXPECTF-- --- Equal --- @@ -121,8 +135,13 @@ int(2) --- Variable selector --- int(1) int(0) +int(1) int(0) --- Corner case --- grapheme_levenshtein(): Argument #3 ($insertion_cost) must be greater than 0 and less than or equal to %d grapheme_levenshtein(): Argument #4 ($replacement_cost) must be greater than 0 and less than or equal to %d grapheme_levenshtein(): Argument #5 ($deletion_cost) must be greater than 0 and less than or equal to %d +--- Invalid locales --- +bool(false) +int(%d) +string(68) "grapheme_levenshtein(): Error on ucol_open: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/grapheme_stripos_locale_dependency.phpt b/ext/intl/tests/grapheme_stripos_locale_dependency.phpt new file mode 100644 index 0000000000000..e1a8d05e2541d --- /dev/null +++ b/ext/intl/tests/grapheme_stripos_locale_dependency.phpt @@ -0,0 +1,23 @@ +--TEST-- +grapheme_stripos() function locale dependency test +--EXTENSIONS-- +intl +--FILE-- + +--EXPECTF-- +int(0) +int(0) +bool(false) +=== Invalid locales === +bool(false) +int(%d) +string(74) "grapheme_stripos(): Error creating search object: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/grapheme_stristr_locale_dependency.phpt b/ext/intl/tests/grapheme_stristr_locale_dependency.phpt new file mode 100644 index 0000000000000..91d0e7273be0c --- /dev/null +++ b/ext/intl/tests/grapheme_stristr_locale_dependency.phpt @@ -0,0 +1,23 @@ +--TEST-- +grapheme_stristr() function locale dependency test +--EXTENSIONS-- +intl +--FILE-- + +--EXPECTF-- +string(3) "abc" +string(1) "i" +bool(false) +=== Invalid locales === +bool(false) +int(%d) +string(74) "grapheme_stristr(): Error creating search object: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/grapheme_strpos_locale_dependency.phpt b/ext/intl/tests/grapheme_strpos_locale_dependency.phpt new file mode 100644 index 0000000000000..f43b54123ab51 --- /dev/null +++ b/ext/intl/tests/grapheme_strpos_locale_dependency.phpt @@ -0,0 +1,12 @@ +--TEST-- +grapheme_strpos() function locale dependency test +--EXTENSIONS-- +intl +--FILE-- + +--EXPECT-- +bool(false) +int(0) diff --git a/ext/intl/tests/grapheme_strripos_locale_dependency.phpt b/ext/intl/tests/grapheme_strripos_locale_dependency.phpt new file mode 100644 index 0000000000000..87e87c483b7a4 --- /dev/null +++ b/ext/intl/tests/grapheme_strripos_locale_dependency.phpt @@ -0,0 +1,23 @@ +--TEST-- +grapheme_strripos() function locale dependency test +--EXTENSIONS-- +intl +--FILE-- + +--EXPECTF-- +int(0) +int(0) +bool(false) +=== Invalid locales === +bool(false) +int(%d) +string(75) "grapheme_strripos(): Error creating search object: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/gregoriancalendar___construct_basic.phpt b/ext/intl/tests/gregoriancalendar___construct_basic.phpt index 315c43f2904a5..8ebe683f8d16e 100644 --- a/ext/intl/tests/gregoriancalendar___construct_basic.phpt +++ b/ext/intl/tests/gregoriancalendar___construct_basic.phpt @@ -2,12 +2,11 @@ IntlGregorianCalendar::__construct(): basic --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Amsterdam +intl.default_locale=nl --FILE-- getTimeZone()->getId()); diff --git a/ext/intl/tests/gregoriancalendar___construct_error.phpt b/ext/intl/tests/gregoriancalendar___construct_error.phpt index 2261da3955bef..6922b7cadd8cf 100644 --- a/ext/intl/tests/gregoriancalendar___construct_error.phpt +++ b/ext/intl/tests/gregoriancalendar___construct_error.phpt @@ -4,7 +4,6 @@ IntlGregorianCalendar::__construct(): bad arguments intl --FILE-- getTimeZone()->getId()); diff --git a/ext/intl/tests/gregoriancalendar_getGregorianChange_error.phpt b/ext/intl/tests/gregoriancalendar_getGregorianChange_error.phpt deleted file mode 100644 index 5665b793f388b..0000000000000 --- a/ext/intl/tests/gregoriancalendar_getGregorianChange_error.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -IntlGregorianCalendar::getGregorianChange(): bad arguments ---INI-- -date.timezone=Atlantic/Azores ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intlgregcal_get_gregorian_change(): Argument #1 ($calendar) must be of type IntlGregorianCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlgregcal_get_gregorian_change(1) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/gregoriancalendar_get_setGregorianChange_basic.phpt b/ext/intl/tests/gregoriancalendar_get_setGregorianChange_basic.phpt index 8ae2410dc8c79..e0cd6b13b2eae 100644 --- a/ext/intl/tests/gregoriancalendar_get_setGregorianChange_basic.phpt +++ b/ext/intl/tests/gregoriancalendar_get_setGregorianChange_basic.phpt @@ -2,12 +2,11 @@ IntlGregorianCalendar::get/setGregorianChange(): basic test --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Amsterdam +intl.default_locale=nl --FILE-- ---EXPECTF-- -Fatal error: Uncaught TypeError: intlgregcal_is_leap_year(): Argument #1 ($calendar) must be of type IntlGregorianCalendar, int given in %s:%d -Stack trace: -#0 %s(%d): intlgregcal_is_leap_year(1, 2) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/idn_uts46_errors.phpt b/ext/intl/tests/idn_uts46_errors.phpt index 1cbf336defa61..c1058c3a2439d 100644 --- a/ext/intl/tests/idn_uts46_errors.phpt +++ b/ext/intl/tests/idn_uts46_errors.phpt @@ -9,7 +9,6 @@ intl ?> --FILE-- PHP level errors", "\n"; echo "bad variant:", "\n"; diff --git a/ext/intl/tests/ini_use_exceptions_basic.phpt b/ext/intl/tests/ini_use_exceptions_basic.phpt index c2aabfbe63f43..e03c991ae05f2 100644 --- a/ext/intl/tests/ini_use_exceptions_basic.phpt +++ b/ext/intl/tests/ini_use_exceptions_basic.phpt @@ -16,7 +16,9 @@ ini_set("intl.error_level", E_NOTICE); var_dump($t->transliterate('a', 3)); ?> --EXPECTF-- -string(130) "transliterator_transliterate: Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 1)" +string(133) "Transliterator::transliterate(): Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 1)" -Notice: Transliterator::transliterate(): transliterator_transliterate: Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 1) in %s on line %d +Deprecated: ini_set(): Using a value different than 0 for intl.error_level is deprecated, as the intl.error_level INI setting is deprecated. Instead the intl.use_exceptions INI setting should be enabled to throw exceptions on errors or intl_get_error_code()/intl_get_error_message() should be used to manually deal with errors in %s on line %d + +Notice: Transliterator::transliterate(): Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 1) in %s on line %d bool(false) diff --git a/ext/intl/tests/intl_get_error_message.phpt b/ext/intl/tests/intl_get_error_message.phpt index 93d2e5c653afa..83130e549dcad 100644 --- a/ext/intl/tests/intl_get_error_message.phpt +++ b/ext/intl/tests/intl_get_error_message.phpt @@ -15,4 +15,4 @@ else ?> --EXPECT-- -Error getting locale by type: U_ILLEGAL_ARGUMENT_ERROR +collator_get_locale(): Error getting locale by type: U_ILLEGAL_ARGUMENT_ERROR diff --git a/ext/intl/tests/listformatter/listformatter_error.phpt b/ext/intl/tests/listformatter/listformatter_error.phpt index d420b92a9f8d8..4ca22136943e8 100644 --- a/ext/intl/tests/listformatter/listformatter_error.phpt +++ b/ext/intl/tests/listformatter/listformatter_error.phpt @@ -33,6 +33,6 @@ try { ?> --EXPECT-- IntlListFormatter::__construct(): Argument #1 ($locale) "f" is invalid -IntlListFormatter::__construct(): Argument #1 ($locale) Locale string too long, should be no longer than 156 characters +IntlListFormatter::__construct(): Argument #1 ($locale) must be less than or equal to 156 characters Object of class stdClass could not be converted to string Object of class stdClass could not be converted to string diff --git a/ext/intl/tests/locale_compose_locale.phpt b/ext/intl/tests/locale_compose_locale.phpt index 0a2a501b9baf9..beaf4beaa8ae1 100644 --- a/ext/intl/tests/locale_compose_locale.phpt +++ b/ext/intl/tests/locale_compose_locale.phpt @@ -13,115 +13,89 @@ intl function ut_main() { $loc_parts_arr1 = array( - Locale::LANG_TAG =>'sl' , - Locale::SCRIPT_TAG =>'Latn' , - Locale::REGION_TAG =>'IT' + Locale::LANG_TAG => 'sl', + Locale::SCRIPT_TAG => 'Latn', + Locale::REGION_TAG => 'IT' ); $loc_parts_arr2 = array( - Locale::LANG_TAG =>'de' , - Locale::REGION_TAG =>'DE' + Locale::LANG_TAG => 'de', + Locale::REGION_TAG => 'DE' ); $loc_parts_arr3 = array( - Locale::LANG_TAG =>'hi' + Locale::LANG_TAG => 'hi' ); $loc_parts_arr4 = array( - Locale::LANG_TAG =>'zh' , - Locale::SCRIPT_TAG =>'Hans' , - Locale::REGION_TAG =>'CN' + Locale::LANG_TAG => 'zh', + Locale::SCRIPT_TAG => 'Hans', + Locale::REGION_TAG => 'CN' ); $loc_parts_arr5 = array( - Locale::LANG_TAG =>'es' , - Locale::SCRIPT_TAG =>'Hans' , - Locale::REGION_TAG =>'CN' + Locale::LANG_TAG => 'es', + Locale::SCRIPT_TAG => 'Hans', + Locale::REGION_TAG => 'CN' ); $loc_parts_arr6 = array( - Locale::LANG_TAG =>'en' , - Locale::SCRIPT_TAG =>'Hans' , - Locale::REGION_TAG =>'CN', - Locale::VARIANT_TAG.'14' =>'rozaj' , - 'variant1'=>'nedis' + Locale::LANG_TAG => 'en', + Locale::SCRIPT_TAG => 'Hans', + Locale::REGION_TAG => 'CN', + Locale::VARIANT_TAG.'14' => 'rozaj', + 'variant1' => 'nedis' ); $loc_parts_arr7 = array( - Locale::LANG_TAG =>'en' , - Locale::SCRIPT_TAG =>'Hans' , - Locale::REGION_TAG =>'CN', - 'variant14'=>'rozaj' , - 'variant1'=>'nedis' , - 'extlang0'=>'lng' , - 'extlang1'=>'ing' + Locale::LANG_TAG => 'en', + Locale::SCRIPT_TAG => 'Hans', + Locale::REGION_TAG => 'CN', + 'variant14' => 'rozaj', + 'variant1' => 'nedis', + 'extlang0' => 'lng', + 'extlang1' => 'ing' ); $loc_parts_arr8 = array( - Locale::LANG_TAG =>'en' , - Locale::SCRIPT_TAG =>'Hans' , - Locale::REGION_TAG =>'CN', - 'variant14'=>'rozaj' , - 'variant1'=>'nedis' , - 'extlang0'=>'lng' , - 'extlang1'=>'ing', - 'private7'=>'prv1' , - 'private9'=>'prv2' + Locale::LANG_TAG => 'en', + Locale::SCRIPT_TAG => 'Hans', + Locale::REGION_TAG => 'CN', + 'variant14' => 'rozaj', + 'variant1' => 'nedis', + 'extlang0' => 'lng', + 'extlang1' => 'ing', + 'private7' => 'prv1', + 'private9' => 'prv2' ); $loc_parts_arr9 = array( - Locale::REGION_TAG =>'DE' - ); - $loc_parts_arr10 = array( - Locale::LANG_TAG => 45, - Locale::REGION_TAG => false, - Locale::SCRIPT_TAG => 15 - ); - $loc_parts_arr11 = array( - Locale::LANG_TAG =>'de' , - Locale::REGION_TAG =>'DE', - 'private0' => 13, - 'variant1' => array(), - 'extlang2' => false - ); - $loc_parts_arr12 = array( - Locale::LANG_TAG =>'en' , - Locale::SCRIPT_TAG =>'Hans' , - Locale::REGION_TAG =>'CN', - Locale::VARIANT_TAG => array('nedis', 'rozaj'), + Locale::LANG_TAG => 'en', + Locale::SCRIPT_TAG => 'Hans', + Locale::REGION_TAG => 'CN', + Locale::VARIANT_TAG => array('nedis', 'rozaj'), Locale::PRIVATE_TAG => array('prv1', 'prv2'), Locale::EXTLANG_TAG => array('lng', 'ing') - ); + ); $loc_parts_arr = array( - 'loc1' => $loc_parts_arr1 , - 'loc2' => $loc_parts_arr2 , - 'loc3' => $loc_parts_arr3 , - 'loc4' => $loc_parts_arr4 , - 'loc5' => $loc_parts_arr5 , - 'loc6' => $loc_parts_arr6 , - 'loc7' => $loc_parts_arr7 , - 'loc8' => $loc_parts_arr8 , - 'loc9' => $loc_parts_arr9 , - 'loc10' => $loc_parts_arr10 , - 'loc11' => $loc_parts_arr11 , - 'loc12' => $loc_parts_arr12 + 'loc1' => $loc_parts_arr1, + 'loc2' => $loc_parts_arr2, + 'loc3' => $loc_parts_arr3, + 'loc4' => $loc_parts_arr4, + 'loc5' => $loc_parts_arr5, + 'loc6' => $loc_parts_arr6, + 'loc7' => $loc_parts_arr7, + 'loc8' => $loc_parts_arr8, + 'loc9' => $loc_parts_arr9, ); $cnt = 0; $res_str = ''; - foreach($loc_parts_arr as $key => $value ){ + foreach ($loc_parts_arr as $key => $value) { $res_str .= "\n------------"; $res_str .= "\nInput Array name is : loc".(++$cnt) ; -/* - foreach($value as $valKey => $valValue ){ - $res_str .= $valKey ."->".$valValue." " ; - } -*/ - try { - $locale = ut_loc_locale_compose( $value); - $res_str .= "\n\nComposed Locale: "; - if( $locale){ - $res_str .= "$locale"; - }else{ - $res_str .= "No values found from Locale compose due to the following error:\n"; - $res_str .= intl_get_error_message() ; - } - } catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; + + $locale = ut_loc_locale_compose( $value); + $res_str .= "\n\nComposed Locale: "; + if ($locale) { + $res_str .= "$locale"; + } else { + $res_str .= "No values found from Locale compose due to the following error:\n"; + $res_str .= intl_get_error_message() ; } } @@ -136,9 +110,6 @@ ut_run(); ?> --EXPECT-- -Locale::composeLocale(): Argument #1 ($subtags) must contain a "language" key -locale_compose(): Argument #1 ($subtags) must contain a "language" key - ------------ Input Array name is : loc1 @@ -173,18 +144,6 @@ Input Array name is : loc8 Composed Locale: en_lng_ing_Hans_CN_nedis_rozaj_x_prv1_prv2 ------------ Input Array name is : loc9 ------------- -Input Array name is : loc10 - -Composed Locale: No values found from Locale compose due to the following error: -locale_compose: parameter array element is not a string: U_ILLEGAL_ARGUMENT_ERROR ------------- -Input Array name is : loc11 - -Composed Locale: No values found from Locale compose due to the following error: -locale_compose: parameter array element is not a string: U_ILLEGAL_ARGUMENT_ERROR ------------- -Input Array name is : loc12 Composed Locale: en_lng_ing_Hans_CN_nedis_rozaj_x_prv1_prv2 ------------ diff --git a/ext/intl/tests/locale_compose_locale_errors.phpt b/ext/intl/tests/locale_compose_locale_errors.phpt new file mode 100644 index 0000000000000..b0d68aae73cee --- /dev/null +++ b/ext/intl/tests/locale_compose_locale_errors.phpt @@ -0,0 +1,58 @@ +--TEST-- +locale_compose_locale() errors +--EXTENSIONS-- +intl +--FILE-- + 45, + Locale::REGION_TAG => false, + Locale::SCRIPT_TAG => 15, +]; + +var_dump(Locale::composeLocale($parts1)); +var_dump(intl_get_error_message()); +var_dump(locale_compose($parts1)); +var_dump(intl_get_error_message()); + +$parts2 = [ + Locale::LANG_TAG => 'de', + Locale::REGION_TAG => 'DE', + 'private0' => 13, + 'variant1' => array(), + 'extlang2' => false +]; + +var_dump(Locale::composeLocale($parts2)); +var_dump(intl_get_error_message()); +var_dump(locale_compose($parts2)); +var_dump(intl_get_error_message()); + +$parts3 = [ + Locale::REGION_TAG => 'DE', +]; + +try { + var_dump(Locale::composeLocale($parts3)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump(locale_compose($parts3)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +bool(false) +string(90) "Locale::composeLocale(): parameter array element is not a string: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(83) "locale_compose(): parameter array element is not a string: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(90) "Locale::composeLocale(): parameter array element is not a string: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(83) "locale_compose(): parameter array element is not a string: U_ILLEGAL_ARGUMENT_ERROR" +ValueError: Locale::composeLocale(): Argument #1 ($subtags) must contain a "language" key +ValueError: locale_compose(): Argument #1 ($subtags) must contain a "language" key diff --git a/ext/intl/tests/locale_subtags.phpt b/ext/intl/tests/locale_subtags.phpt index 0c454706225b5..f6cb7d1e957de 100644 --- a/ext/intl/tests/locale_subtags.phpt +++ b/ext/intl/tests/locale_subtags.phpt @@ -26,10 +26,10 @@ bool(true) bool(true) bool(true) bool(false) -string(67) "locale_add_likely_subtags: invalid locale: U_ILLEGAL_ARGUMENT_ERROR" +string(68) "Locale::addLikelySubtags(): invalid locale: U_ILLEGAL_ARGUMENT_ERROR" bool(false) -string(65) "locale_minimize_subtags: invalid locale: U_ILLEGAL_ARGUMENT_ERROR" +string(67) "Locale::minimizeSubtags(): invalid locale: U_ILLEGAL_ARGUMENT_ERROR" bool(false) -string(%d) "locale_add_likely_subtags: invalid locale: %s" +string(68) "Locale::addLikelySubtags(): invalid locale: U_ILLEGAL_ARGUMENT_ERROR" bool(false) -string(%d) "locale_minimize_subtags: invalid locale: %s" +string(%d) "Locale::minimizeSubtags(): invalid locale: %s" diff --git a/ext/intl/tests/msgfmt_errors.phpt b/ext/intl/tests/msgfmt_errors.phpt new file mode 100644 index 0000000000000..78264c22b3ad3 --- /dev/null +++ b/ext/intl/tests/msgfmt_errors.phpt @@ -0,0 +1,30 @@ +--TEST-- +MessageFormatter with invalid locale +--EXTENSIONS-- +intl +--FILE-- +getMessage(), PHP_EOL; +} + +$mf = MessageFormatter::create('root', $fmt); +var_dump($mf); +var_dump(intl_get_error_message()); + +$mf = msgfmt_create('root', $fmt); +var_dump($mf); +var_dump(intl_get_error_message()); + +?> +--EXPECT-- +IntlException: MessageFormatter::__construct(): message formatter creation failed +NULL +string(87) "MessageFormatter::create(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR" +NULL +string(76) "msgfmt_create(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/msgfmt_fail2.phpt b/ext/intl/tests/msgfmt_fail2.phpt index a5256e724a02d..de592e7b798c7 100644 --- a/ext/intl/tests/msgfmt_fail2.phpt +++ b/ext/intl/tests/msgfmt_fail2.phpt @@ -130,23 +130,23 @@ Deprecated: MessageFormatter::__construct(): Passing null to parameter #1 ($loca Deprecated: MessageFormatter::__construct(): Passing null to parameter #2 ($pattern) of type string is deprecated in %s on line %d -IntlException: msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR in %s on line %d -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' +IntlException: MessageFormatter::__construct(): message formatter creation failed in %s on line %d +'MessageFormatter::__construct(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' Deprecated: MessageFormatter::create(): Passing null to parameter #1 ($locale) of type string is deprecated in %s on line %d Deprecated: MessageFormatter::create(): Passing null to parameter #2 ($pattern) of type string is deprecated in %s on line %d -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' +'MessageFormatter::create(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' Deprecated: msgfmt_create(): Passing null to parameter #1 ($locale) of type string is deprecated in %s on line %d Deprecated: msgfmt_create(): Passing null to parameter #2 ($pattern) of type string is deprecated in %s on line %d -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' +'msgfmt_create(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' -IntlException: msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR in %s on line %d -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' +IntlException: MessageFormatter::__construct(): message formatter creation failed in %s on line %d +'MessageFormatter::__construct(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' +'MessageFormatter::create(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' +'msgfmt_create(): message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' TypeError: MessageFormatter::__construct(): Argument #1 ($locale) must be of type string, array given in %s on line %d 'U_ZERO_ERROR' @@ -157,17 +157,17 @@ TypeError: MessageFormatter::create(): Argument #1 ($locale) must be of type str TypeError: msgfmt_create(): Argument #1 ($locale) must be of type string, array given in %s on line %d 'U_ZERO_ERROR' -IntlException: pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR in %s on line %d -'pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR' -'pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR' -'pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR' +IntlException: MessageFormatter::__construct(): pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}") in %s on line %d +'MessageFormatter::__construct(): pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR' +'MessageFormatter::create(): pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR' +'msgfmt_create(): pattern syntax error (parse error at offset 1, after "{", before or at "0,choice}"): U_PATTERN_SYNTAX_ERROR' -IntlException: msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES in %s on line %d -'msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES' -'msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES' -'msgfmt_create: message formatter creation failed: U_UNMATCHED_BRACES' +IntlException: MessageFormatter::__construct(): message formatter creation failed in %s on line %d +'MessageFormatter::__construct(): message formatter creation failed: U_UNMATCHED_BRACES' +'MessageFormatter::create(): message formatter creation failed: U_UNMATCHED_BRACES' +'msgfmt_create(): message formatter creation failed: U_UNMATCHED_BRACES' -IntlException: msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND in %s on line %d -'msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND' -'msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND' -'msgfmt_create: error converting pattern to UTF-16: U_INVALID_CHAR_FOUND' +IntlException: MessageFormatter::__construct(): error converting pattern to UTF-16 in %s on line %d +'MessageFormatter::__construct(): error converting pattern to UTF-16: U_INVALID_CHAR_FOUND' +'MessageFormatter::create(): error converting pattern to UTF-16: U_INVALID_CHAR_FOUND' +'msgfmt_create(): error converting pattern to UTF-16: U_INVALID_CHAR_FOUND' diff --git a/ext/intl/tests/msgfmt_format.phpt b/ext/intl/tests/msgfmt_format.phpt index 39efaf36c4e31..99440a882e34e 100644 --- a/ext/intl/tests/msgfmt_format.phpt +++ b/ext/intl/tests/msgfmt_format.phpt @@ -17,13 +17,13 @@ function ut_main() 'ru_UA' => "{0,number,integer} мавп на {1,number,integer} деревах це {2,number} мавпи на кожному деревi", 'de' => "{0,number,integer} Affen über {1,number,integer} Bäume um {2,number} Affen pro Baum", 'en_UK' => "{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree", - 'root' => '{0,whatever} would not work!', - 'fr' => "C'est la vie!", + 'fr' => "C'est la vie!", ); $str_res = ''; $m = 4560; $t = 123; + $v = [$m, $t, $m/$t]; foreach( $locales as $locale => $pattern ) { @@ -33,8 +33,8 @@ function ut_main() $str_res .= dump(intl_get_error_message())."\n"; continue; } - $str_res .= dump( ut_msgfmt_format( $fmt, array($m, $t, $m/$t) ) ) . "\n"; - $str_res .= dump( ut_msgfmt_format_message($locale, $pattern, array($m, $t, $m/$t))) . "\n"; + $str_res .= dump( ut_msgfmt_format( $fmt, $v) ) . "\n"; + $str_res .= dump( ut_msgfmt_format_message($locale, $pattern, $v)) . "\n"; } return $str_res; } @@ -62,9 +62,6 @@ Locale is: en_UK '4,560 monkeys on 123 trees make 37.073 monkeys per tree' '4,560 monkeys on 123 trees make 37.073 monkeys per tree' -Locale is: root -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' - Locale is: fr 'C\'est la vie!' 'C\'est la vie!' diff --git a/ext/intl/tests/msgfmt_format_datetime.phpt b/ext/intl/tests/msgfmt_format_datetime.phpt index e6a7451906f77..7ee35e643e221 100644 --- a/ext/intl/tests/msgfmt_format_datetime.phpt +++ b/ext/intl/tests/msgfmt_format_datetime.phpt @@ -1,15 +1,11 @@ --TEST-- MessageFormatter::format(): DateTime accepted to format dates and times ---INI-- -date.timezone=Atlantic/Azores --EXTENSIONS-- intl --SKIPIF-- = 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> --FILE-- format(array(7))); +try { + var_dump($mf->format(array(7))); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Warning: MessageFormatter::format(): Inconsistent types declared for an argument in %s on line %d -bool(false) +--EXPECT-- +IntlException: MessageFormatter::format(): Inconsistent types declared for an argument diff --git a/ext/intl/tests/msgfmt_format_error3.phpt b/ext/intl/tests/msgfmt_format_error3.phpt index f9c44789dc23a..a03b0a21ecc42 100644 --- a/ext/intl/tests/msgfmt_format_error3.phpt +++ b/ext/intl/tests/msgfmt_format_error3.phpt @@ -2,17 +2,21 @@ MessageFormatter::format() given negative arg key --EXTENSIONS-- intl +--INI-- +intl.use_exceptions=On --FILE-- format(array("foo" => 7, -1 => "bar"))); +try { + var_dump($mf->format(array("foo" => 7, -1 => "bar"))); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Warning: MessageFormatter::format(): Found negative or too large array key in %s on line %d -bool(false) +--EXPECT-- +IntlException: MessageFormatter::format(): Found negative or too large array key diff --git a/ext/intl/tests/msgfmt_format_error4.phpt b/ext/intl/tests/msgfmt_format_error4.phpt index a6f5912723087..451a55ad9da94 100644 --- a/ext/intl/tests/msgfmt_format_error4.phpt +++ b/ext/intl/tests/msgfmt_format_error4.phpt @@ -2,22 +2,32 @@ MessageFormatter::format() invalid UTF-8 for arg key or value --EXTENSIONS-- intl +--INI-- +intl.use_exceptions=On --FILE-- format(array("foo" => 7, "\x80" => "bar"))); +try { + var_dump($mf->format(array("foo" => 7, "\x80" => "bar"))); +} catch (Throwable $e) { + var_dump($e::class === 'IntlException'); + var_dump("MessageFormatter::format(): Invalid UTF-8 data in argument key: '\x80'" === $e->getMessage()); +} -var_dump($mf->format(array("foo" => "\x80"))); +try { + var_dump($mf->format(array("foo" => "\x80"))); +} catch (Throwable $e) { + var_dump($e::class === 'IntlException'); + var_dump("MessageFormatter::format(): Invalid UTF-8 data in string argument: '\x80'" === $e->getMessage()); +} ?> ---EXPECTF-- -Warning: MessageFormatter::format(): Invalid UTF-8 data in argument key: '' in %s on line %d -bool(false) - -Warning: MessageFormatter::format(): Invalid UTF-8 data in string argument: '' in %s on line %d -bool(false) +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/ext/intl/tests/msgfmt_format_error5.phpt b/ext/intl/tests/msgfmt_format_error5.phpt index f3f87835b9217..d5d7e6a4dc8e6 100644 --- a/ext/intl/tests/msgfmt_format_error5.phpt +++ b/ext/intl/tests/msgfmt_format_error5.phpt @@ -2,21 +2,22 @@ MessageFormatter::format() invalid date/time argument --INI-- date.timezone=Atlantic/Azores +intl.use_exceptions=On --EXTENSIONS-- intl --FILE-- format(array("foo" => new stdclass()))); +try { + var_dump($mf->format(array("foo" => new stdclass()))); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Warning: MessageFormatter::format(): msgfmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted) in %s on line %d - -Warning: MessageFormatter::format(): The argument for key 'foo' cannot be used as a date or time in %s on line %d -bool(false) +--EXPECT-- +IntlException: MessageFormatter::format(): The argument for key 'foo' cannot be used as a date or time diff --git a/ext/intl/tests/msgfmt_format_error6.phpt b/ext/intl/tests/msgfmt_format_error6.phpt index 23db397282265..9320194be6f3f 100644 --- a/ext/intl/tests/msgfmt_format_error6.phpt +++ b/ext/intl/tests/msgfmt_format_error6.phpt @@ -2,17 +2,21 @@ MessageFormatter::format() invalid type for key not in pattern --EXTENSIONS-- intl +--INI-- +intl.use_exceptions=On --FILE-- format(array("foo" => 'bar', 7 => fopen('php://memory', 'r+')))); +try { + var_dump($mf->format(array("foo" => 'bar', 7 => fopen('php://memory', 'r+')))); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Warning: MessageFormatter::format(): No strategy to convert the value given for the argument with key '7' is available in %s on line %d -bool(false) +--EXPECT-- +IntlException: MessageFormatter::format(): No strategy to convert the value given for the argument with key '7' is available diff --git a/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt b/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt index 0b8e607ad2db1..014bdd4749bca 100644 --- a/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt +++ b/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt @@ -2,6 +2,8 @@ MessageFormat accepts IntlCalendar args --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Lisbon --SKIPIF-- --FILE-- +--EXPECT-- +bool(false) +string(82) "MessageFormatter::formatMessage(): Creating message formatter failed: U_ZERO_ERROR" +bool(false) +string(72) "msgfmt_format_message(): Creating message formatter failed: U_ZERO_ERROR" diff --git a/ext/intl/tests/msgfmt_format_mixed_params.phpt b/ext/intl/tests/msgfmt_format_mixed_params.phpt index 016dbe96be4af..3cfb210099932 100644 --- a/ext/intl/tests/msgfmt_format_mixed_params.phpt +++ b/ext/intl/tests/msgfmt_format_mixed_params.phpt @@ -4,8 +4,6 @@ MessageFormatter::format(): mixed named and numeric parameters intl --FILE-- = 0) die('skip for ICU < 72.1'); ?> --FILE-- = 72.1'); ?> --FILE-- "{0,number,integer} мавп на {1,number,integer} деревах це {2,number} мавпи на кожному деревi", 'de' => "{0,number,integer} Affen über {1,number,integer} Bäume um {2,number} Affen pro Baum", 'en_UK' => "{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree", - 'root' => '{0,whatever} would not work!', - 'fr' => 'C\'est {0,number,integer}', + 'fr' => 'C\'est {0,number,integer}', ); $results = array( @@ -26,7 +25,6 @@ function ut_main() 'ru_UA' => "4 560 мавп на 123 деревах це 37,073 мавпи на кожному деревi", 'de' => "4.560 Affen über 123 Bäume um 37,073 Affen pro Baum", 'en_UK' => "4,560 monkeys on 123 trees make 37.073 monkeys per tree", - 'root' => "4,560 monkeys on 123 trees make 37.073 monkeys per tree", 'fr' => "C'est 42", ); @@ -102,9 +100,6 @@ array ( 2 => 37.073, ) -Locale is: root -'msgfmt_create: message formatter creation failed: U_ILLEGAL_ARGUMENT_ERROR' - Locale is: fr array ( 0 => 42, diff --git a/ext/intl/tests/msgfmt_parse_message_errors.phpt b/ext/intl/tests/msgfmt_parse_message_errors.phpt new file mode 100644 index 0000000000000..7bd0780fa6420 --- /dev/null +++ b/ext/intl/tests/msgfmt_parse_message_errors.phpt @@ -0,0 +1,27 @@ +--TEST-- +MessageFormatter::parseMessage() with invalid locale +--EXTENSIONS-- +intl +--CREDITS-- +girgias@php.net +--FILE-- + +--EXPECT-- +bool(false) +string(93) "MessageFormatter::parseMessage(): Creating message formatter failed: U_ILLEGAL_ARGUMENT_ERROR" +bool(false) +string(83) "msgfmt_parse_message(): Creating message formatter failed: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/msgfmt_setPattern_cache.phpt b/ext/intl/tests/msgfmt_setPattern_cache.phpt index 7aff410f082e8..9b5af2542031e 100644 --- a/ext/intl/tests/msgfmt_setPattern_cache.phpt +++ b/ext/intl/tests/msgfmt_setPattern_cache.phpt @@ -4,8 +4,6 @@ MessageFormatter::setPattern() invalidates arg types cache intl --FILE-- setPattern($broken); +var_dump($mf->getErrorMessage()); + +msgfmt_set_pattern($mf, $broken); +var_dump($mf->getErrorMessage()); + +?> +--EXPECT-- +string(103) "MessageFormatter::setPattern(): Error setting symbol value at line 0, offset 26: U_PATTERN_SYNTAX_ERROR" +string(93) "msgfmt_set_pattern(): Error setting symbol value at line 0, offset 26: U_PATTERN_SYNTAX_ERROR" diff --git a/ext/intl/tests/normalizer_get_raw_decomposition.phpt b/ext/intl/tests/normalizer_get_raw_decomposition.phpt index efb4424c80c97..678a85491fdce 100644 --- a/ext/intl/tests/normalizer_get_raw_decomposition.phpt +++ b/ext/intl/tests/normalizer_get_raw_decomposition.phpt @@ -2,67 +2,52 @@ normalizer_get_raw_decomposition() --EXTENSIONS-- intl ---SKIPIF-- - --FILE-- --EXPECT-- ---------------------- -'61' has no decomposition mapping -error info: 'U_ZERO_ERROR' (0) ---------------------- -'efbf9a' has the decomposition mapping 'e385a1' -error info: 'U_ZERO_ERROR' (0) ---------------------- -'efb7ba' has the decomposition mapping 'd8b5d984d98920d8a7d984d984d98720d8b9d984d98ad98720d988d8b3d984d985' -error info: 'U_ZERO_ERROR' (0) ---------------------- -'' has no decomposition mapping -error info: 'Input string must be exactly one UTF-8 encoded code point long.: U_ILLEGAL_ARGUMENT_ERROR' (1) ---------------------- -'6161' has no decomposition mapping -error info: 'Input string must be exactly one UTF-8 encoded code point long.: U_ILLEGAL_ARGUMENT_ERROR' (1) ---------------------- -'f5' has no decomposition mapping -error info: 'Code point out of range: U_ILLEGAL_ARGUMENT_ERROR' (1) +'a' has no decomposition mapping +'a' has no decomposition mapping +string(3) "ㅡ" +string(3) "ㅡ" +string(33) "صلى الله عليه وسلم" +string(33) "صلى الله عليه وسلم" +string(124) "Normalizer::getRawDecomposition(): Input string must be exactly one UTF-8 encoded code point long.: U_ILLEGAL_ARGUMENT_ERROR" +string(125) "normalizer_get_raw_decomposition(): Input string must be exactly one UTF-8 encoded code point long.: U_ILLEGAL_ARGUMENT_ERROR" +string(124) "Normalizer::getRawDecomposition(): Input string must be exactly one UTF-8 encoded code point long.: U_ILLEGAL_ARGUMENT_ERROR" +string(125) "normalizer_get_raw_decomposition(): Input string must be exactly one UTF-8 encoded code point long.: U_ILLEGAL_ARGUMENT_ERROR" +string(84) "Normalizer::getRawDecomposition(): Code point out of range: U_ILLEGAL_ARGUMENT_ERROR" +string(85) "normalizer_get_raw_decomposition(): Code point out of range: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/rbbiter___construct_basic.phpt b/ext/intl/tests/rbbiter___construct_basic.phpt index 6d2361f667b32..e749442daa9f4 100644 --- a/ext/intl/tests/rbbiter___construct_basic.phpt +++ b/ext/intl/tests/rbbiter___construct_basic.phpt @@ -2,9 +2,10 @@ IntlRuleBasedBreakIterator::__construct: basic test --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT --FILE-- = 0) die('skip for ICU < 61.1'); ?> --FILE-- = 61.1 && icu < 68.1 --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT --SKIPIF-- = 61.1'; ?> = 0) die('skip for ICU < 68.1'); ?> --FILE-- = 68.1 --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT --SKIPIF-- = 68.1'); ?> --FILE-- = 0) die('skip for ICU < 61.1'); ?> --FILE-- = 61.1 && icu < 68.1 --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT --SKIPIF-- = 61.1'); ?> = 0) die('skip for ICU < 68.1'); ?> --FILE-- = 68.1 --EXTENSIONS-- intl +--INI-- +intl.default_locale=pt_PT --SKIPIF-- = 68.1'); ?> --FILE-- getMessage(), PHP_EOL; +} + +$rb = resourcebundle_create('en_US', 'non-existing'); +var_dump($rb); +var_dump(intl_get_error_message()); + +require_once "resourcebundle.inc"; + +try { + $rb = new ResourceBundle('en_US', BUNDLE, false); + var_dump($rb); + var_dump(intl_get_error_message()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +$rb = resourcebundle_create('en_US', BUNDLE, false); +var_dump($rb); +var_dump(intl_get_error_message()); + +?> +--EXPECT-- +IntlException: ResourceBundle::__construct(): Cannot load libICU resource bundle +NULL +string(85) "resourcebundle_create(): Cannot load libICU resource bundle: U_MISSING_RESOURCE_ERROR" +IntlException: ResourceBundle::__construct(): Cannot load libICU resource bundle +NULL +string(85) "resourcebundle_create(): Cannot load libICU resource bundle: U_MISSING_RESOURCE_ERROR" diff --git a/ext/intl/tests/resourcebundle_get_errors.phpt b/ext/intl/tests/resourcebundle_get_errors.phpt new file mode 100644 index 0000000000000..28952b816107a --- /dev/null +++ b/ext/intl/tests/resourcebundle_get_errors.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test ResourceBundle::get() missing keys +--EXTENSIONS-- +intl +--FILE-- +get('nonexisting')); +var_dump(intl_get_error_message()); + +var_dump(resourcebundle_get($bundle, 'nonexisting')); +var_dump(intl_get_error_message()); + +// Make sure accessing existing after non-existing works. +var_dump($bundle->get('teststring')); + +?> +--EXPECT-- +NULL +string(91) "ResourceBundle::get(): Cannot load resource element 'nonexisting': U_MISSING_RESOURCE_ERROR" +NULL +string(90) "resourcebundle_get(): Cannot load resource element 'nonexisting': U_MISSING_RESOURCE_ERROR" +string(12) "Hello World!" diff --git a/ext/intl/tests/resourcebundle_individual.phpt b/ext/intl/tests/resourcebundle_individual.phpt index d9be94b464b1b..089c485dc8ab3 100644 --- a/ext/intl/tests/resourcebundle_individual.phpt +++ b/ext/intl/tests/resourcebundle_individual.phpt @@ -1,5 +1,5 @@ --TEST-- -Test ResourceBundle::get() and length() - existing/missing keys +Test ResourceBundle::get() and length() - existing keys --EXTENSIONS-- intl --FILE-- @@ -25,13 +25,6 @@ function ut_main() { $r2 = ut_resourcebundle_get($r,'testarray' ); $str_res .= sprintf( "testarray: %s\n", ut_resourcebundle_get($r2, 2 ) ); - $t = ut_resourcebundle_get( $r, 'nonexisting' ); - $str_res .= debug( $t ); - - // Make sure accessing existing after non-existing works. - $t = ut_resourcebundle_get( $r, 'teststring' ); - $str_res .= debug( $t ); - return $str_res; } include_once( 'ut_common.inc' ); @@ -57,7 +50,3 @@ Array testbin: a1b2c3d4e5f67890 testtable: 3 testarray: string 3 -NULL - 2: Cannot load resource element 'nonexisting': U_MISSING_RESOURCE_ERROR -Hello World! - 0: U_ZERO_ERROR diff --git a/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt b/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt index 9d13be94aed55..b49e30317b3d8 100644 --- a/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt +++ b/ext/intl/tests/resourcebundle_null_mandatory_args_variant2.phpt @@ -8,7 +8,6 @@ intl = 0) die('skip for ICU < 72.1'); ?> --FILE-- get('calendar')->get('gregorian')->get('DateTimePatterns')->get(0); diff --git a/ext/intl/tests/resourcebundle_null_mandatory_args_variant_icu72-1.phpt b/ext/intl/tests/resourcebundle_null_mandatory_args_variant_icu72-1.phpt index d3e2615e0f494..98fa0c47305c7 100644 --- a/ext/intl/tests/resourcebundle_null_mandatory_args_variant_icu72-1.phpt +++ b/ext/intl/tests/resourcebundle_null_mandatory_args_variant_icu72-1.phpt @@ -8,7 +8,6 @@ intl = 72.1'); ?> --FILE-- get('calendar')->get('gregorian')->get('DateTimePatterns')->get(0); diff --git a/ext/intl/tests/timezone_IDforWindowsID_basic.phpt b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt index 8626223cb8bb4..8e1fcbb4a8fc3 100644 --- a/ext/intl/tests/timezone_IDforWindowsID_basic.phpt +++ b/ext/intl/tests/timezone_IDforWindowsID_basic.phpt @@ -8,7 +8,6 @@ intl array(NULL), 'India Standard Time' => array(NULL), 'Pacific Standard Time' => array('001', 'CA', 'MX', 'US', 'ZZ'), 'Romance Standard Time' => array('001', 'BE', 'DK', 'ES', 'FR'), @@ -25,9 +24,6 @@ foreach ($tzs as $tz => $regions) { } ?> --EXPECT-- -** Gnomeregan -bool(false) -Error: intltz_get_windows_id: Unknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR ** India Standard Time string(13) "Asia/Calcutta" ** Pacific Standard Time diff --git a/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt b/ext/intl/tests/timezone_IDforWindowsID_basic_icu58_1.phpt similarity index 91% rename from ext/intl/tests/timezone_IDforWindowsID_basic2.phpt rename to ext/intl/tests/timezone_IDforWindowsID_basic_icu58_1.phpt index 600e21fa70c80..b92ebb89ec207 100644 --- a/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt +++ b/ext/intl/tests/timezone_IDforWindowsID_basic_icu58_1.phpt @@ -9,7 +9,6 @@ intl array(NULL), 'India Standard Time' => array(NULL), 'Pacific Standard Time' => array('001', 'CA', 'MX', 'US', 'ZZ'), 'Romance Standard Time' => array('001', 'BE', 'DK', 'ES', 'FR'), @@ -26,9 +25,6 @@ foreach ($tzs as $tz => $regions) { } ?> --EXPECTF-- -** Gnomeregan -bool(false) -Error: unknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR ** India Standard Time string(13) "Asia/Calcutta" ** Pacific Standard Time diff --git a/ext/intl/tests/timezone_IDforWindowsID_basic_icu76_1.phpt b/ext/intl/tests/timezone_IDforWindowsID_basic_icu76_1.phpt index 96de341974b1a..d07c14797c654 100644 --- a/ext/intl/tests/timezone_IDforWindowsID_basic_icu76_1.phpt +++ b/ext/intl/tests/timezone_IDforWindowsID_basic_icu76_1.phpt @@ -8,7 +8,6 @@ intl array(NULL), 'India Standard Time' => array(NULL), 'Pacific Standard Time' => array('001', 'CA', 'MX', 'US', 'ZZ'), 'Romance Standard Time' => array('001', 'BE', 'DK', 'ES', 'FR'), @@ -24,10 +23,7 @@ foreach ($tzs as $tz => $regions) { } } ?> ---EXPECTF-- -** Gnomeregan -bool(false) -Error: %snknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR +--EXPECT-- ** India Standard Time string(13) "Asia/Calcutta" ** Pacific Standard Time diff --git a/ext/intl/tests/timezone_IDforWindowsID_error.phpt b/ext/intl/tests/timezone_IDforWindowsID_error.phpt new file mode 100644 index 0000000000000..1160ce9f91a0f --- /dev/null +++ b/ext/intl/tests/timezone_IDforWindowsID_error.phpt @@ -0,0 +1,14 @@ +--TEST-- +IntlTimeZone::getIDForWindowsID() errors +--EXTENSIONS-- +intl +--FILE-- + +--EXPECT-- +bool(false) +string(85) "IntlTimeZone::getIDForWindowsID(): unknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/timezone_clone_basic.phpt b/ext/intl/tests/timezone_clone_basic.phpt index c09ffe4620334..db13884d272d9 100644 --- a/ext/intl/tests/timezone_clone_basic.phpt +++ b/ext/intl/tests/timezone_clone_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone clone handler: basic test intl --FILE-- GMT [rawOffset] => 0 [currentOffset] => 0 -) \ No newline at end of file +) diff --git a/ext/intl/tests/timezone_countEquivalentIDs_basic.phpt b/ext/intl/tests/timezone_countEquivalentIDs_basic.phpt index 2fa3a7d249fdd..25fa0f8839bdd 100644 --- a/ext/intl/tests/timezone_countEquivalentIDs_basic.phpt +++ b/ext/intl/tests/timezone_countEquivalentIDs_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::countEquivalentIDs(): basic test intl --FILE-- = 2); @@ -13,4 +12,4 @@ var_dump($count2 == $count); ?> --EXPECT-- bool(true) -bool(true) \ No newline at end of file +bool(true) diff --git a/ext/intl/tests/timezone_countEquivalentIDs_error.phpt b/ext/intl/tests/timezone_countEquivalentIDs_error.phpt index 23f95e129f1d0..5eab5f881da8c 100644 --- a/ext/intl/tests/timezone_countEquivalentIDs_error.phpt +++ b/ext/intl/tests/timezone_countEquivalentIDs_error.phpt @@ -4,10 +4,11 @@ IntlTimeZone::countEquivalentIDs(): errors intl --FILE-- ---EXPECTF-- -Warning: IntlTimeZone::countEquivalentIDs(): could not convert time zone id to UTF-16 in %s on line %d +--EXPECT-- bool(false) +IntlTimeZone::countEquivalentIDs(): could not convert time zone id to UTF-16: U_INVALID_CHAR_FOUND diff --git a/ext/intl/tests/timezone_createDefault_basic.phpt b/ext/intl/tests/timezone_createDefault_basic.phpt index 82ba9c94564cc..2281e9e35bf5b 100644 --- a/ext/intl/tests/timezone_createDefault_basic.phpt +++ b/ext/intl/tests/timezone_createDefault_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::createDefault(): basic test intl --FILE-- getMessage(), PHP_EOL; +} + +try { + var_dump(IntlTimeZone::createEnumeration(new stdClass())); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- -Warning: IntlTimeZone::createEnumeration(): invalid argument type in %s on line %d -bool(false) +--EXPECT-- +TypeError: IntlTimeZone::createEnumeration(): Argument #1 ($countryOrRawOffset) must be of type string|int|null, array given +TypeError: IntlTimeZone::createEnumeration(): Argument #1 ($countryOrRawOffset) must be of type string|int|null, stdClass given diff --git a/ext/intl/tests/timezone_createEnumeration_variation1.phpt b/ext/intl/tests/timezone_createEnumeration_variation1.phpt index 5dfe9f893e0f1..96a73779bfa25 100644 --- a/ext/intl/tests/timezone_createEnumeration_variation1.phpt +++ b/ext/intl/tests/timezone_createEnumeration_variation1.phpt @@ -4,7 +4,6 @@ IntlTimeZone::createEnumeration(): variant with offset intl --FILE-- --EXPECT-- -Array -( - [0] => Atlantic/Azores -) -Array -( - [0] => Atlantic/Azores -) +array(1) { + [0]=> + string(15) "Atlantic/Azores" +} +array(1) { + [0]=> + string(15) "Atlantic/Azores" +} diff --git a/ext/intl/tests/timezone_createTimeZoneIDEnumeration_error.phpt b/ext/intl/tests/timezone_createTimeZoneIDEnumeration_error.phpt index 2173c4a5cd12a..0eb26b826a347 100644 --- a/ext/intl/tests/timezone_createTimeZoneIDEnumeration_error.phpt +++ b/ext/intl/tests/timezone_createTimeZoneIDEnumeration_error.phpt @@ -1,13 +1,16 @@ --TEST-- -IntlTimeZone::createTimeZoneIDEnumeration(): errors +IntlTimeZone::createTimeZoneIDEnumeration() invalid zone type --EXTENSIONS-- intl --FILE-- getMessage(), PHP_EOL; +} + ?> ---EXPECTF-- -Warning: IntlTimeZone::createTimeZoneIDEnumeration(): bad zone type in %s on line %d -bool(false) +--EXPECT-- +ValueError: IntlTimeZone::createTimeZoneIDEnumeration(): Argument #1 ($type) must be one of IntlTimeZone::TYPE_ANY, IntlTimeZone::TYPE_CANONICAL, or IntlTimeZone::TYPE_CANONICAL_LOCATION diff --git a/ext/intl/tests/timezone_createTimeZoneIDEnumeration_error_64bit.phpt b/ext/intl/tests/timezone_createTimeZoneIDEnumeration_error_64bit.phpt new file mode 100644 index 0000000000000..1e6791a172ca6 --- /dev/null +++ b/ext/intl/tests/timezone_createTimeZoneIDEnumeration_error_64bit.phpt @@ -0,0 +1,17 @@ +--TEST-- +IntlTimeZone::createTimeZoneIDEnumeration() offset out of range +--EXTENSIONS-- +intl +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} +?> +--EXPECT-- +ValueError: IntlTimeZone::createTimeZoneIDEnumeration(): Argument #3 ($rawOffset) must be between -2147483648 and 2147483647 diff --git a/ext/intl/tests/timezone_createTimeZoneIDEnumeration_variant1.phpt b/ext/intl/tests/timezone_createTimeZoneIDEnumeration_variant1.phpt index ff940aa725df0..34523d0037d8a 100644 --- a/ext/intl/tests/timezone_createTimeZoneIDEnumeration_variant1.phpt +++ b/ext/intl/tests/timezone_createTimeZoneIDEnumeration_variant1.phpt @@ -4,7 +4,6 @@ IntlTimeZone::createTimeZoneIDEnumeration(): variant without offset intl --FILE-- Atlantic/Azores - [1] => Etc/GMT+1 -) +array(2) { + [0]=> + string(15) "Atlantic/Azores" + [1]=> + string(9) "Etc/GMT+1" +} diff --git a/ext/intl/tests/timezone_createTimeZone_basic.phpt b/ext/intl/tests/timezone_createTimeZone_basic.phpt index c3ffe289672fd..1a3549cafdf75 100644 --- a/ext/intl/tests/timezone_createTimeZone_basic.phpt +++ b/ext/intl/tests/timezone_createTimeZone_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::createTimeZone(): basic test intl --FILE-- ---EXPECTF-- -Warning: IntlTimeZone::createTimeZone(): could not convert time zone id to UTF-16 in %s on line %d +--EXPECT-- NULL +IntlTimeZone::createTimeZone(): could not convert time zone id to UTF-16: U_INVALID_CHAR_FOUND diff --git a/ext/intl/tests/timezone_equals_basic.phpt b/ext/intl/tests/timezone_equals_basic.phpt index 04636a4f7c4c8..224f9c9229a34 100644 --- a/ext/intl/tests/timezone_equals_basic.phpt +++ b/ext/intl/tests/timezone_equals_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone equals handler: basic test intl --FILE-- getMessage()); + var_dump($tz == $tz2); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } ?> @@ -35,5 +34,4 @@ object(IntlTimeZone)#2 (4) { ["currentOffset"]=> int(0) } -string(9) "Exception" -string(63) "Comparison with at least one unconstructed IntlTimeZone operand" \ No newline at end of file +Exception: Comparison with at least one unconstructed IntlTimeZone operand diff --git a/ext/intl/tests/timezone_fromDateTimeZone_basic.phpt b/ext/intl/tests/timezone_fromDateTimeZone_basic.phpt index 45443c78a1666..3e9597de0bb84 100644 --- a/ext/intl/tests/timezone_fromDateTimeZone_basic.phpt +++ b/ext/intl/tests/timezone_fromDateTimeZone_basic.phpt @@ -2,11 +2,11 @@ IntlTimeZone::fromDateTimeZone(): basic test --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Lisbon +intl.default_locale=nl --FILE-- getID(), $tz->getRawOffset()); diff --git a/ext/intl/tests/timezone_fromDateTimeZone_error.phpt b/ext/intl/tests/timezone_fromDateTimeZone_error.phpt index fe2a04453033a..acd608bc376c1 100644 --- a/ext/intl/tests/timezone_fromDateTimeZone_error.phpt +++ b/ext/intl/tests/timezone_fromDateTimeZone_error.phpt @@ -6,11 +6,12 @@ date.timezone=Atlantic/Azores intl --FILE-- getTimeZone())); +var_dump(intl_get_error_message()); + ?> ---EXPECTF-- -Warning: IntlTimeZone::fromDateTimeZone(): intltz_from_date_time_zone: time zone id 'WEST' extracted from ext/date DateTimeZone not recognized in %s on line %d +--EXPECT-- NULL +string(131) "IntlTimeZone::fromDateTimeZone(): time zone id 'WEST' extracted from ext/date DateTimeZone not recognized: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/timezone_getCanonicalID_basic.phpt b/ext/intl/tests/timezone_getCanonicalID_basic.phpt index 7660b04e2647a..0bc18e4c8b650 100644 --- a/ext/intl/tests/timezone_getCanonicalID_basic.phpt +++ b/ext/intl/tests/timezone_getCanonicalID_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::getCanonicalID: basic test intl --FILE-- --EXPECT-- Europe/Lisbon -Europe/Lisbon \ No newline at end of file +Europe/Lisbon diff --git a/ext/intl/tests/timezone_getCanonicalID_error.phpt b/ext/intl/tests/timezone_getCanonicalID_error.phpt index d85805555a38f..542d3ca3fa410 100644 --- a/ext/intl/tests/timezone_getCanonicalID_error.phpt +++ b/ext/intl/tests/timezone_getCanonicalID_error.phpt @@ -4,10 +4,11 @@ IntlTimeZone::getCanonicalID(): errors intl --FILE-- ---EXPECTF-- -Warning: IntlTimeZone::getCanonicalID(): could not convert time zone id to UTF-16 in %s on line %d +--EXPECT-- bool(false) +IntlTimeZone::getCanonicalID(): could not convert time zone id to UTF-16: U_INVALID_CHAR_FOUND diff --git a/ext/intl/tests/timezone_getCanonicalID_variant1_2.phpt b/ext/intl/tests/timezone_getCanonicalID_variant1_2.phpt index 3fedf4377197a..d883bb06ebdbc 100644 --- a/ext/intl/tests/timezone_getCanonicalID_variant1_2.phpt +++ b/ext/intl/tests/timezone_getCanonicalID_variant1_2.phpt @@ -4,20 +4,21 @@ IntlTimeZone::getCanonicalID(): second argument intl --FILE-- ---EXPECTF-- +--EXPECT-- string(13) "Europe/Lisbon" +U_ZERO_ERROR bool(true) - -Warning: IntlTimeZone::getCanonicalID(): error obtaining canonical ID in %stimezone_getCanonicalID_variant1_2.php on line %d bool(false) +IntlTimeZone::getCanonicalID(): error obtaining canonical ID: U_ILLEGAL_ARGUMENT_ERROR bool(true) diff --git a/ext/intl/tests/timezone_getDSTSavings_basic.phpt b/ext/intl/tests/timezone_getDSTSavings_basic.phpt index 1a0b5554322f5..469e4b5791c0e 100644 --- a/ext/intl/tests/timezone_getDSTSavings_basic.phpt +++ b/ext/intl/tests/timezone_getDSTSavings_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::getDSTSavings(): basic test intl --FILE-- getDSTSavings()); @@ -14,4 +13,4 @@ var_dump(intltz_get_dst_savings($lsb)); ?> --EXPECT-- int(3600000) -int(3600000) \ No newline at end of file +int(3600000) diff --git a/ext/intl/tests/timezone_getDSTSavings_error.phpt b/ext/intl/tests/timezone_getDSTSavings_error.phpt deleted file mode 100644 index c444aab645338..0000000000000 --- a/ext/intl/tests/timezone_getDSTSavings_error.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -IntlTimeZone::getDSTSavings(): errors ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intltz_get_dst_savings(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_get_dst_savings(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/timezone_getDisplayName_basic.phpt b/ext/intl/tests/timezone_getDisplayName_basic.phpt index 6db1596b38085..a80eeb762d1bb 100644 --- a/ext/intl/tests/timezone_getDisplayName_basic.phpt +++ b/ext/intl/tests/timezone_getDisplayName_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::getDisplayName(): basic test intl --FILE-- getDisplayName()); ?> --EXPECTF-- string(%d) "Western European%sTime" -string(%d) "Hora%sda Europa Ocidental" \ No newline at end of file +string(%d) "Hora%sda Europa Ocidental" diff --git a/ext/intl/tests/timezone_getDisplayName_error.phpt b/ext/intl/tests/timezone_getDisplayName_error.phpt index ce3ab2f7e766e..ca845b2830ed2 100644 --- a/ext/intl/tests/timezone_getDisplayName_error.phpt +++ b/ext/intl/tests/timezone_getDisplayName_error.phpt @@ -4,19 +4,12 @@ IntlTimeZone::getDisplayName(): errors intl --FILE-- getDisplayName(false, -1)); +echo intl_get_error_message(), PHP_EOL; -var_dump(intltz_get_display_name(null, IntlTimeZone::DISPLAY_SHORT, false, 'pt_PT')); ?> ---EXPECTF-- -Warning: IntlTimeZone::getDisplayName(): wrong display type in %s on line %d +--EXPECT-- bool(false) - -Fatal error: Uncaught TypeError: intltz_get_display_name(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_get_display_name(NULL, 1, false, 'pt_PT') -#1 {main} - thrown in %s on line %d +IntlTimeZone::getDisplayName(): wrong display type: U_ILLEGAL_ARGUMENT_ERROR diff --git a/ext/intl/tests/timezone_getDisplayName_variant1.phpt b/ext/intl/tests/timezone_getDisplayName_variant1.phpt index 60c11ee91273e..684e564779c64 100644 --- a/ext/intl/tests/timezone_getDisplayName_variant1.phpt +++ b/ext/intl/tests/timezone_getDisplayName_variant1.phpt @@ -2,15 +2,13 @@ IntlTimeZone::getDisplayName(): daylight parameter effect --EXTENSIONS-- intl +--INI-- +intl.default_locale=en_US --FILE-- getDisplayName()); var_dump($lsb->getDisplayName(false)); var_dump($lsb->getDisplayName(true)); @@ -19,4 +17,4 @@ var_dump($lsb->getDisplayName(true)); --EXPECTF-- string(%d) "Western European%sTime" string(%d) "Western European%sTime" -string(28) "Western European Summer Time" \ No newline at end of file +string(28) "Western European Summer Time" diff --git a/ext/intl/tests/timezone_getDisplayName_variant4.phpt b/ext/intl/tests/timezone_getDisplayName_variant4.phpt index eccf6c78d2ca4..39d71f5aa2011 100644 --- a/ext/intl/tests/timezone_getDisplayName_variant4.phpt +++ b/ext/intl/tests/timezone_getDisplayName_variant4.phpt @@ -2,15 +2,13 @@ IntlTimeZone::getDisplayName(): type parameter (ICU >= 51.2) --EXTENSIONS-- intl +--INI-- +intl.default_locale=en_US --FILE-- getDisplayName(false, IntlTimeZone::DISPLAY_SHORT)); var_dump($lsb->getDisplayName(false, IntlTimeZone::DISPLAY_LONG)); var_dump($lsb->getDisplayName(false, IntlTimeZone::DISPLAY_SHORT_GENERIC)); diff --git a/ext/intl/tests/timezone_getEquivalentID_basic.phpt b/ext/intl/tests/timezone_getEquivalentID_basic.phpt index 2e311bc8664e2..7702b01506ed2 100644 --- a/ext/intl/tests/timezone_getEquivalentID_basic.phpt +++ b/ext/intl/tests/timezone_getEquivalentID_basic.phpt @@ -4,12 +4,11 @@ IntlTimeZone::getEquivalentID(): basic test intl --FILE-- --EXPECT-- -Portugal -Portugal \ No newline at end of file +string(8) "Portugal" +string(8) "Portugal" diff --git a/ext/intl/tests/timezone_getEquivalentID_error.phpt b/ext/intl/tests/timezone_getEquivalentID_error.phpt index ebb85fb1334a9..c6b1a963daf71 100644 --- a/ext/intl/tests/timezone_getEquivalentID_error.phpt +++ b/ext/intl/tests/timezone_getEquivalentID_error.phpt @@ -4,10 +4,11 @@ IntlTimeZone::getEquivalentID(): errors intl --FILE-- ---EXPECTF-- -Warning: IntlTimeZone::getEquivalentID(): could not convert time zone id to UTF-16 in %s on line %d +--EXPECT-- bool(false) +IntlTimeZone::getEquivalentID(): could not convert time zone id to UTF-16: U_INVALID_CHAR_FOUND diff --git a/ext/intl/tests/timezone_getErrorCodeMessage_basic.phpt b/ext/intl/tests/timezone_getErrorCodeMessage_basic.phpt index 597e9b51a0fce..be991baf5f674 100644 --- a/ext/intl/tests/timezone_getErrorCodeMessage_basic.phpt +++ b/ext/intl/tests/timezone_getErrorCodeMessage_basic.phpt @@ -11,24 +11,23 @@ if ($arch != 'x86_64' && $arch != 'i386') ?> --FILE-- getErrorCode()); var_dump($lsb->getErrorMessage()); +echo "Call to getOffset():\n"; var_dump($lsb->getOffset(INF, 1, $a, $b)); var_dump($lsb->getErrorCode()); var_dump($lsb->getErrorMessage()); ?> ---EXPECTF-- +--EXPECT-- int(0) string(12) "U_ZERO_ERROR" - -Warning: IntlTimeZone::getOffset(): error obtaining offset in %s on line %d +Call to getOffset(): bool(false) int(1) -string(48) "error obtaining offset: U_ILLEGAL_ARGUMENT_ERROR" +string(75) "IntlTimeZone::getOffset(): error obtaining offset: U_ILLEGAL_ARGUMENT_ERROR" diff --git a/ext/intl/tests/timezone_getErrorCode_error.phpt b/ext/intl/tests/timezone_getErrorCode_error.phpt deleted file mode 100644 index 3b91977c69b08..0000000000000 --- a/ext/intl/tests/timezone_getErrorCode_error.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -IntlTimeZone::getErrorCode(): errors ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intltz_get_error_code(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_get_error_code(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/timezone_getErrorMessage_error.phpt b/ext/intl/tests/timezone_getErrorMessage_error.phpt deleted file mode 100644 index 80c5ec02f5a94..0000000000000 --- a/ext/intl/tests/timezone_getErrorMessage_error.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -IntlTimeZone::getErrorMessage(): errors ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intltz_get_error_message(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_get_error_message(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/timezone_getGMT_basic.phpt b/ext/intl/tests/timezone_getGMT_basic.phpt index becc52fd3e146..d58b555bbe24f 100644 --- a/ext/intl/tests/timezone_getGMT_basic.phpt +++ b/ext/intl/tests/timezone_getGMT_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::getGMT(): basic test intl --FILE-- GMT [rawOffset] => 0 [currentOffset] => 0 -) \ No newline at end of file +) diff --git a/ext/intl/tests/timezone_getID_error.phpt b/ext/intl/tests/timezone_getID_error.phpt deleted file mode 100644 index 44b305f464dd2..0000000000000 --- a/ext/intl/tests/timezone_getID_error.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -IntlTimeZone::getID(): errors ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intltz_get_id(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_get_id(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/timezone_getIanaID.phpt b/ext/intl/tests/timezone_getIanaID.phpt index 7f728e48ec5f6..1db39c398d6f3 100644 --- a/ext/intl/tests/timezone_getIanaID.phpt +++ b/ext/intl/tests/timezone_getIanaID.phpt @@ -6,20 +6,24 @@ intl = 74.0'); ?> --FILE-- ---EXPECTF-- -Warning: IntlTimeZone::getIanaID(): could not convert time zone id to UTF-16 in %s on line %d +--EXPECT-- bool(false) - -Warning: IntlTimeZone::getIanaID(): error obtaining IANA ID in %s on line %d +IntlTimeZone::getIanaID(): could not convert time zone id to UTF-16: U_INVALID_CHAR_FOUND bool(false) +IntlTimeZone::getIanaID(): error obtaining IANA ID: U_ILLEGAL_ARGUMENT_ERROR string(13) "Europe/Dublin" +U_ZERO_ERROR string(12) "Asia/Kolkata" +U_ZERO_ERROR bool(true) diff --git a/ext/intl/tests/timezone_getOffset_basic.phpt b/ext/intl/tests/timezone_getOffset_basic.phpt index 2f86869479c25..55c2fa7caee12 100644 --- a/ext/intl/tests/timezone_getOffset_basic.phpt +++ b/ext/intl/tests/timezone_getOffset_basic.phpt @@ -6,7 +6,6 @@ date.timezone=Atlantic/Azores intl --FILE-- --FILE-- getOffset(INF, true, $a, $a)); +echo intl_get_error_message(), PHP_EOL; -intltz_get_offset(null, time()*1000, false, $a, $a); ?> ---EXPECTF-- -Warning: IntlTimeZone::getOffset(): error obtaining offset in %s on line %d +--EXPECT-- bool(false) - -Fatal error: Uncaught TypeError: intltz_get_offset(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_get_offset(NULL, %f, false, NULL, NULL) -#1 {main} - thrown in %s on line %d +IntlTimeZone::getOffset(): error obtaining offset: U_ILLEGAL_ARGUMENT_ERROR diff --git a/ext/intl/tests/timezone_getRawOffset_basic.phpt b/ext/intl/tests/timezone_getRawOffset_basic.phpt index 734df41375c42..545f1f1f8d87c 100644 --- a/ext/intl/tests/timezone_getRawOffset_basic.phpt +++ b/ext/intl/tests/timezone_getRawOffset_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::getRawOffset(): basic test intl --FILE-- getRawOffset()); @@ -14,4 +13,4 @@ var_dump(intltz_get_raw_offset($lsb)); ?> --EXPECT-- int(3600000) -int(0) \ No newline at end of file +int(0) diff --git a/ext/intl/tests/timezone_getRawOffset_error.phpt b/ext/intl/tests/timezone_getRawOffset_error.phpt deleted file mode 100644 index cc508ddbbebcc..0000000000000 --- a/ext/intl/tests/timezone_getRawOffset_error.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -IntlTimeZone::getRawOffset(): errors ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: intltz_get_raw_offset(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_get_raw_offset(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/timezone_getRegion_basic.phpt b/ext/intl/tests/timezone_getRegion_basic.phpt index 4aecd30e87d2a..b156cb674559b 100644 --- a/ext/intl/tests/timezone_getRegion_basic.phpt +++ b/ext/intl/tests/timezone_getRegion_basic.phpt @@ -4,12 +4,11 @@ IntlTimeZone::getRegion(): basic test intl --FILE-- --EXPECT-- -NL -NL +string(2) "NL" +string(2) "NL" diff --git a/ext/intl/tests/timezone_getRegion_error.phpt b/ext/intl/tests/timezone_getRegion_error.phpt index 70acbaa6fbca0..d5ef9f2ae92ef 100644 --- a/ext/intl/tests/timezone_getRegion_error.phpt +++ b/ext/intl/tests/timezone_getRegion_error.phpt @@ -4,14 +4,15 @@ IntlTimeZone::getRegion(): errors intl --FILE-- ---EXPECTF-- -Warning: IntlTimeZone::getRegion(): could not convert time zone id to UTF-16 in %s on line %d +--EXPECT-- bool(false) - -Warning: IntlTimeZone::getRegion(): error obtaining region in %s on line %d +IntlTimeZone::getRegion(): could not convert time zone id to UTF-16: U_INVALID_CHAR_FOUND bool(false) +IntlTimeZone::getRegion(): error obtaining region: U_ILLEGAL_ARGUMENT_ERROR diff --git a/ext/intl/tests/timezone_getTZData_basic.phpt b/ext/intl/tests/timezone_getTZData_basic.phpt index bf0b3dfb9348d..99d21357b5568 100644 --- a/ext/intl/tests/timezone_getTZData_basic.phpt +++ b/ext/intl/tests/timezone_getTZData_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::getTZDataVersion: basic test intl --FILE-- --EXPECTF-- 20%d%s -20%d%s \ No newline at end of file +20%d%s diff --git a/ext/intl/tests/timezone_getUnknown_basic.phpt b/ext/intl/tests/timezone_getUnknown_basic.phpt index a7c2ac58177ec..71785fc656c55 100644 --- a/ext/intl/tests/timezone_getUnknown_basic.phpt +++ b/ext/intl/tests/timezone_getUnknown_basic.phpt @@ -4,7 +4,6 @@ IntlCalendar::getUnknown(): basic test intl --FILE-- hasSameRules('foo')); -} catch (Error $ex) { - var_dump($ex->getCode(), $ex->getMessage()); - echo "\n"; -} - -try { - var_dump(intltz_has_same_rules(null, $tz)); -} catch (Error $ex) { - var_dump($ex->getCode(), $ex->getMessage()); - echo "\n"; -} -?> ---EXPECT-- -int(0) -string(93) "IntlTimeZone::hasSameRules(): Argument #1 ($other) must be of type IntlTimeZone, string given" - -int(0) -string(89) "intltz_has_same_rules(): Argument #1 ($timezone) must be of type IntlTimeZone, null given" diff --git a/ext/intl/tests/timezone_toDateTimeZone_basic.phpt b/ext/intl/tests/timezone_toDateTimeZone_basic.phpt index d82f65d7c0f4a..bd5f6809d7e20 100644 --- a/ext/intl/tests/timezone_toDateTimeZone_basic.phpt +++ b/ext/intl/tests/timezone_toDateTimeZone_basic.phpt @@ -2,11 +2,11 @@ IntlTimeZone::toDateTimeZone(): basic test --EXTENSIONS-- intl +--INI-- +date.timezone=Europe/Lisbon +intl.default_locale=nl --FILE-- getID(), $tz->getRawOffset()); diff --git a/ext/intl/tests/timezone_toDateTimeZone_error.phpt b/ext/intl/tests/timezone_toDateTimeZone_error.phpt index 7355185541bc8..8ba5be884b425 100644 --- a/ext/intl/tests/timezone_toDateTimeZone_error.phpt +++ b/ext/intl/tests/timezone_toDateTimeZone_error.phpt @@ -4,24 +4,18 @@ IntlTimeZone::toDateTimeZone(): errors intl --FILE-- toDateTimeZone()); -} catch (Exception $e) { - var_dump($e->getMessage()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; + $previous = $e->getPrevious(); + echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL; } -var_dump(intltz_to_date_time_zone(1)); ?> ---EXPECTF-- -Warning: IntlTimeZone::toDateTimeZone(): intltz_to_date_time_zone: DateTimeZone constructor threw exception in %s on line %d -string(66) "DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)" - -Fatal error: Uncaught TypeError: intltz_to_date_time_zone(): Argument #1 ($timezone) must be of type IntlTimeZone, int given in %s:%d -Stack trace: -#0 %s(%d): intltz_to_date_time_zone(1) -#1 {main} - thrown in %s on line %d +--EXPECT-- +IntlException: DateTimeZone constructor threw exception + DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown) diff --git a/ext/intl/tests/timezone_useDaylightTime_basic.phpt b/ext/intl/tests/timezone_useDaylightTime_basic.phpt index 2f8d02c2d154c..3451739bb70f7 100644 --- a/ext/intl/tests/timezone_useDaylightTime_basic.phpt +++ b/ext/intl/tests/timezone_useDaylightTime_basic.phpt @@ -4,7 +4,6 @@ IntlTimeZone::useDaylightTime: basic test intl --FILE-- ---EXPECTF-- -Fatal error: Uncaught TypeError: intltz_use_daylight_time(): Argument #1 ($timezone) must be of type IntlTimeZone, null given in %s:%d -Stack trace: -#0 %s(%d): intltz_use_daylight_time(NULL) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/timezone_windowsID_basic2.phpt b/ext/intl/tests/timezone_windowsID_basic2.phpt index aa1ce7f886c4c..0db032207fa9d 100644 --- a/ext/intl/tests/timezone_windowsID_basic2.phpt +++ b/ext/intl/tests/timezone_windowsID_basic2.phpt @@ -33,7 +33,7 @@ string(18) "Cuba Standard Time" string(21) "Central Standard Time" string(21) "Pacific Standard Time" bool(false) -Error: unknown system timezone: U_ILLEGAL_ARGUMENT_ERROR +Error: IntlTimeZone::getWindowsID(): unknown system timezone: U_ILLEGAL_ARGUMENT_ERROR string(21) "Morocco Standard Time" string(23) "Singapore Standard Time" string(26) "W. Australia Standard Time" diff --git a/ext/intl/tests/transliterator_clone.phpt b/ext/intl/tests/transliterator_clone.phpt index 057e2a7aef444..ccbe56ea6af5b 100644 --- a/ext/intl/tests/transliterator_clone.phpt +++ b/ext/intl/tests/transliterator_clone.phpt @@ -4,7 +4,6 @@ Transliterator clone handler intl --FILE-- id,"\n"; diff --git a/ext/intl/tests/transliterator_create_error.phpt b/ext/intl/tests/transliterator_create_error.phpt index b554fb0dce5cf..fd7db47a42eff 100644 --- a/ext/intl/tests/transliterator_create_error.phpt +++ b/ext/intl/tests/transliterator_create_error.phpt @@ -5,18 +5,14 @@ intl --FILE-- ---EXPECTF-- -Warning: Transliterator::create(): transliterator_create: unable to open ICU transliterator with id "inexistent id" in %s on line %d -transliterator_create: unable to open ICU transliterator with id "inexistent id": U_INVALID_ID - -Warning: Transliterator::create(): String conversion of id to UTF-16 failed in %s on line %d -String conversion of id to UTF-16 failed: U_INVALID_CHAR_FOUND -Done. +--EXPECT-- +NULL +Transliterator::create(): unable to open ICU transliterator with id "inexistent id": U_INVALID_ID +NULL +Transliterator::create(): String conversion of id to UTF-16 failed: U_INVALID_CHAR_FOUND diff --git a/ext/intl/tests/transliterator_create_from_rule_basic.phpt b/ext/intl/tests/transliterator_create_from_rule_basic.phpt index 5c9aa182b5224..02f0b0362b78f 100644 --- a/ext/intl/tests/transliterator_create_from_rule_basic.phpt +++ b/ext/intl/tests/transliterator_create_from_rule_basic.phpt @@ -4,7 +4,6 @@ Transliterator::createFromRules (basic) intl --FILE-- y; diff --git a/ext/intl/tests/transliterator_create_from_rule_error.phpt b/ext/intl/tests/transliterator_create_from_rule_error.phpt index 9a3b86944c8e3..e6f885bfbc8ff 100644 --- a/ext/intl/tests/transliterator_create_from_rule_error.phpt +++ b/ext/intl/tests/transliterator_create_from_rule_error.phpt @@ -4,7 +4,6 @@ Transliterator::createFromRules (error) intl --FILE-- ---EXPECTF-- -Warning: Transliterator::createFromRules(): String conversion of rules to UTF-16 failed in %s on line %d -String conversion of rules to UTF-16 failed: U_INVALID_CHAR_FOUND - -Warning: Transliterator::createFromRules(): transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error after "{'``'}a > “;", before or at "{'``'}a > b;") in %s on line %d -transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error after "{'``'}a > “;", before or at "{'``'}a > b;"): U_RULE_MASK_ERROR - -Warning: Transliterator::createFromRules(): transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error at offset 0, before or at "ffff") in %s on line %d -transliterator_create_from_rules: unable to create ICU transliterator from rules (parse error at offset 0, before or at "ffff"): U_MISSING_OPERATOR +--EXPECT-- +Transliterator::createFromRules(): String conversion of rules to UTF-16 failed: U_INVALID_CHAR_FOUND +Transliterator::createFromRules(): unable to create ICU transliterator from rules (parse error after "{'``'}a > “;", before or at "{'``'}a > b;"): U_RULE_MASK_ERROR +Transliterator::createFromRules(): unable to create ICU transliterator from rules (parse error at offset 0, before or at "ffff"): U_MISSING_OPERATOR Done. diff --git a/ext/intl/tests/transliterator_create_inverse_basic.phpt b/ext/intl/tests/transliterator_create_inverse_basic.phpt index 7206d61ea070f..ed9187b4c0446 100644 --- a/ext/intl/tests/transliterator_create_inverse_basic.phpt +++ b/ext/intl/tests/transliterator_create_inverse_basic.phpt @@ -5,8 +5,6 @@ intl --FILE-- transliterate($orstr); diff --git a/ext/intl/tests/transliterator_create_inverse_error.phpt b/ext/intl/tests/transliterator_create_inverse_error.phpt deleted file mode 100644 index a229a2eb79056..0000000000000 --- a/ext/intl/tests/transliterator_create_inverse_error.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Transliterator::createInverse (error) ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: transliterator_create_inverse(): Argument #1 ($transliterator) must be of type Transliterator, string given in %s:%d -Stack trace: -#0 %s(%d): transliterator_create_inverse('jj') -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/transliterator_get_error_code_basic.phpt b/ext/intl/tests/transliterator_get_error_code_basic.phpt deleted file mode 100644 index 8fb59aa8b87d4..0000000000000 --- a/ext/intl/tests/transliterator_get_error_code_basic.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -Transliterator::getErrorCode (basic) ---EXTENSIONS-- -intl ---FILE-- -transliterate("\x8F")); -echo transliterator_get_error_code($t), "\n"; - -echo $t->getErrorCode(), "\n"; - -var_dump($t->transliterate("")); -echo $t->getErrorCode(), "\n"; - -echo "Done.\n"; -?> ---EXPECTF-- -Warning: Transliterator::transliterate(): String conversion of string to UTF-16 failed in %s on line %d -bool(false) -10 -10 -string(0) "" -0 -Done. diff --git a/ext/intl/tests/transliterator_get_error_code_error.phpt b/ext/intl/tests/transliterator_get_error_code_error.phpt deleted file mode 100644 index bb90e4ab6a439..0000000000000 --- a/ext/intl/tests/transliterator_get_error_code_error.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Transliterator::getErrorCode (error) ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: transliterator_get_error_code(): Argument #1 ($transliterator) must be of type Transliterator, array given in %s:%d -Stack trace: -#0 %s(%d): transliterator_get_error_code(Array) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/transliterator_get_error_message_basic.phpt b/ext/intl/tests/transliterator_get_error_message_basic.phpt index 3c4c9eca513fd..6f5ae0e4d0ee4 100644 --- a/ext/intl/tests/transliterator_get_error_message_basic.phpt +++ b/ext/intl/tests/transliterator_get_error_message_basic.phpt @@ -1,26 +1,23 @@ --TEST-- -Transliterator::getErrorMessage (basic) +Transliterator::getErrorMessage() and Transliterator::getErrorCode()(basic) --EXTENSIONS-- intl --FILE-- transliterate("\x8F")); -echo transliterator_get_error_message($t), "\n"; -echo $t->getErrorMessage(), "\n"; +echo transliterator_get_error_code($t), ': ', transliterator_get_error_message($t), "\n"; + +echo $t->getErrorCode(), ': ', $t->getErrorMessage(), "\n"; var_dump($t->transliterate("")); -echo $t->getErrorMessage(), "\n"; +echo $t->getErrorCode(), ': ', $t->getErrorMessage(), "\n"; -echo "Done.\n"; ?> ---EXPECTF-- -Warning: Transliterator::transliterate(): String conversion of string to UTF-16 failed in %s on line %d +--EXPECT-- bool(false) -String conversion of string to UTF-16 failed: U_INVALID_CHAR_FOUND -String conversion of string to UTF-16 failed: U_INVALID_CHAR_FOUND +10: Transliterator::transliterate(): String conversion of string to UTF-16 failed: U_INVALID_CHAR_FOUND +10: Transliterator::transliterate(): String conversion of string to UTF-16 failed: U_INVALID_CHAR_FOUND string(0) "" -U_ZERO_ERROR -Done. +0: U_ZERO_ERROR diff --git a/ext/intl/tests/transliterator_get_error_message_error.phpt b/ext/intl/tests/transliterator_get_error_message_error.phpt deleted file mode 100644 index 8449c3671d45d..0000000000000 --- a/ext/intl/tests/transliterator_get_error_message_error.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Transliterator::getErrorMessage (error) ---EXTENSIONS-- -intl ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught TypeError: transliterator_get_error_message(): Argument #1 ($transliterator) must be of type Transliterator, array given in %s:%d -Stack trace: -#0 %s(%d): transliterator_get_error_message(Array) -#1 {main} - thrown in %s on line %d diff --git a/ext/intl/tests/transliterator_list_ids_basic.phpt b/ext/intl/tests/transliterator_list_ids_basic.phpt index f6ffb06e81dda..8a808cd69459d 100644 --- a/ext/intl/tests/transliterator_list_ids_basic.phpt +++ b/ext/intl/tests/transliterator_list_ids_basic.phpt @@ -5,7 +5,6 @@ intl --FILE-- 100); var_dump(count(Transliterator::listIDs()) > 100); diff --git a/ext/intl/tests/transliterator_transliterate_error.phpt b/ext/intl/tests/transliterator_transliterate_error.phpt index 4a354465bf21d..e11de9333d4ce 100644 --- a/ext/intl/tests/transliterator_transliterate_error.phpt +++ b/ext/intl/tests/transliterator_transliterate_error.phpt @@ -2,31 +2,34 @@ Transliterator::transliterate (error) --EXTENSIONS-- intl +--INI-- +intl.use_exceptions=true --FILE-- getMessage(), PHP_EOL; +} try { - transliterator_transliterate($tr,"str",7,6); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; + transliterator_transliterate($tr, "str", 7, 6); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } //bad UTF-8 -transliterator_transliterate($tr, "\x80\x03"); +try { + transliterator_transliterate($tr, "\x80\x03"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} -echo "Done.\n"; ?> ---EXPECTF-- -Warning: transliterator_transliterate(): transliterator_transliterate: Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 3) in %s on line %d -bool(false) -transliterator_transliterate(): Argument #2 ($string) must be less than or equal to argument #3 ($end) - -Warning: transliterator_transliterate(): String conversion of string to UTF-16 failed in %s on line %d -Done. +--EXPECT-- +IntlException: transliterator_transliterate(): Neither "start" nor the "end" arguments can exceed the number of UTF-16 code units (in this case, 3) +ValueError: transliterator_transliterate(): Argument #2 ($string) must be less than or equal to argument #3 ($end) +IntlException: transliterator_transliterate(): String conversion of string to UTF-16 failed diff --git a/ext/intl/tests/transliterator_transliterate_variant1.phpt b/ext/intl/tests/transliterator_transliterate_variant1.phpt index 0e288ee63d254..1cc76cd244ab1 100644 --- a/ext/intl/tests/transliterator_transliterate_variant1.phpt +++ b/ext/intl/tests/transliterator_transliterate_variant1.phpt @@ -2,37 +2,32 @@ transliterator_transliterate (variant 1, non-transliterator 1st arg) --EXTENSIONS-- intl +--INI-- +intl.use_exceptions=true --FILE-- getMessage(), PHP_EOL; +} class A { -function __toString() { return "inexistent id"; } + function __toString() { return "inexistent id"; } } -echo transliterator_transliterate(new A(), $str), "\n"; -echo intl_get_error_message(), "\n"; - -echo "Done.\n"; +try { + echo transliterator_transliterate(new A(), $str), "\n"; +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> ---EXPECTF-- +--EXPECT-- \u0020o - -Warning: transliterator_transliterate(): String conversion of id to UTF-16 failed in %s on line %d - -Warning: transliterator_transliterate(): Could not create transliterator with ID %s - -String conversion of id to UTF-16 failed: U_INVALID_CHAR_FOUND - -Warning: transliterator_transliterate(): transliterator_create: unable to open ICU transliterator with id "inexistent id" in %s on line %d - -Warning: transliterator_transliterate(): Could not create transliterator with ID "inexistent id" (transliterator_create: unable to open ICU transliterator with id "inexistent id": U_INVALID_ID) in %s on line %d - -transliterator_create: unable to open ICU transliterator with id "inexistent id": U_INVALID_ID -Done. +IntlException: transliterator_transliterate(): String conversion of id to UTF-16 failed +IntlException: transliterator_transliterate(): unable to open ICU transliterator with id "inexistent id" diff --git a/ext/intl/tests/uconverter___construct_error.phpt b/ext/intl/tests/uconverter___construct_error.phpt index 92adc4a718622..7237f799f8858 100644 --- a/ext/intl/tests/uconverter___construct_error.phpt +++ b/ext/intl/tests/uconverter___construct_error.phpt @@ -1,15 +1,22 @@ --TEST-- Basic UConverter::convert() usage ---INI-- -intl.error_level = E_WARNING --EXTENSIONS-- intl --FILE-- ---EXPECTF-- -Warning: UConverter::__construct(): ucnv_open() returned error 4: U_FILE_ACCESS_ERROR in %s on line %d -object(UConverter)#%d (0) { +try { + $c = new UConverter("\x80", 'utf-8'); + var_dump($c); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + $c = new UConverter('utf-8', "\x80"); + var_dump($c); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; } +?> +--EXPECT-- +IntlException: UConverter::__construct(): returned error 4: U_FILE_ACCESS_ERROR +IntlException: UConverter::__construct(): returned error 4: U_FILE_ACCESS_ERROR diff --git a/ext/intl/tests/uconverter_bug66873.phpt b/ext/intl/tests/uconverter_bug66873.phpt index 9ea684fbd389d..68a01eee93dcb 100644 --- a/ext/intl/tests/uconverter_bug66873.phpt +++ b/ext/intl/tests/uconverter_bug66873.phpt @@ -4,9 +4,13 @@ Bug #66873 - crash in UConverter with invalid encoding intl --FILE-- toUCallback(1, 1, 1, $b); var_dump($o->getErrorCode()); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} ?> --EXPECT-- -int(27) +IntlException: UConverter::__construct(): returned error 4: U_FILE_ACCESS_ERROR diff --git a/ext/intl/tests/uconverter_func_subst.phpt b/ext/intl/tests/uconverter_func_subst.phpt index f8a32e814bb44..8d6553fc98344 100644 --- a/ext/intl/tests/uconverter_func_subst.phpt +++ b/ext/intl/tests/uconverter_func_subst.phpt @@ -1,5 +1,5 @@ --TEST-- -Basic UConverter::convert() w/ Subsitution +Basic UConverter::convert() w/ Substitution --EXTENSIONS-- intl --INI-- @@ -25,7 +25,7 @@ foreach(array('?','','??') as $subst) { --EXPECT-- string(23) "This is an ascii string" string(12) "Snowman: (?)" -Error: transcode() returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR -Error: transcode() returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR -Error: transcode() returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR -Error: transcode() returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR +Error: UConverter::transcode(): returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR +Error: UConverter::transcode(): returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR +Error: UConverter::transcode(): returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR +Error: UConverter::transcode(): returned error 1: U_ILLEGAL_ARGUMENT_ERROR: U_ILLEGAL_ARGUMENT_ERROR diff --git a/ext/intl/tests/uconverter_getDestinationEncoding.phpt b/ext/intl/tests/uconverter_getDestinationEncoding.phpt index d354f2a5682fd..ca1a9b4d5a405 100644 --- a/ext/intl/tests/uconverter_getDestinationEncoding.phpt +++ b/ext/intl/tests/uconverter_getDestinationEncoding.phpt @@ -2,8 +2,6 @@ UConverter::getDestinationEncoding() --CREDITS-- Andy McNeice - PHP Testfest 2017 ---INI-- -intl.error_level = E_WARNING --EXTENSIONS-- intl --FILE-- diff --git a/ext/intl/tests/uconverter_getSourceEncoding.phpt b/ext/intl/tests/uconverter_getSourceEncoding.phpt index 1bd99f81de005..2065f83e9b5f9 100644 --- a/ext/intl/tests/uconverter_getSourceEncoding.phpt +++ b/ext/intl/tests/uconverter_getSourceEncoding.phpt @@ -2,8 +2,6 @@ UConverter::getSourceEncoding() --CREDITS-- Andy McNeice - PHP Testfest 2017 ---INI-- -intl.error_level = E_WARNING --EXTENSIONS-- intl --FILE-- diff --git a/ext/intl/tests/uconverter_setSourceEncoding.phpt b/ext/intl/tests/uconverter_setSourceEncoding.phpt index 3ad539bf80b79..c29558d546aa6 100644 --- a/ext/intl/tests/uconverter_setSourceEncoding.phpt +++ b/ext/intl/tests/uconverter_setSourceEncoding.phpt @@ -2,8 +2,6 @@ UConverter::setSourceEncoding() --CREDITS-- Andy McNeice - PHP Testfest 2017 ---INI-- -intl.error_level = E_WARNING --EXTENSIONS-- intl --FILE-- diff --git a/ext/intl/timezone/timezone.stub.php b/ext/intl/timezone/timezone.stub.php index c879bb9ce55ed..8a8927f7cd8a2 100644 --- a/ext/intl/timezone/timezone.stub.php +++ b/ext/intl/timezone/timezone.stub.php @@ -45,11 +45,10 @@ public static function countEquivalentIDs(string $timezoneId): int|false {} public static function createDefault(): IntlTimeZone {} /** - * @param IntlTimeZone|string|int|float|null $countryOrRawOffset * @tentative-return-type * @alias intltz_create_enumeration */ - public static function createEnumeration($countryOrRawOffset = null): IntlIterator|false {} + public static function createEnumeration(string|int|null $countryOrRawOffset = null): IntlIterator|false {} /** * @tentative-return-type diff --git a/ext/intl/timezone/timezone_arginfo.h b/ext/intl/timezone/timezone_arginfo.h index 6206e03efad3e..e30e9806d9d53 100644 --- a/ext/intl/timezone/timezone_arginfo.h +++ b/ext/intl/timezone/timezone_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 6ffeea8491aa48c49879fa77bdb644d10d5c71bd */ + * Stub hash: 22e652c6a05ade0a6fd3119e4742cd260ba27146 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlTimeZone___construct, 0, 0, 0) ZEND_END_ARG_INFO() @@ -12,7 +12,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_IntlTimeZone_crea ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_IntlTimeZone_createEnumeration, 0, 0, IntlIterator, MAY_BE_FALSE) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, countryOrRawOffset, "null") + ZEND_ARG_TYPE_MASK(0, countryOrRawOffset, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_IntlTimeZone_createTimeZone, 0, 1, IntlTimeZone, 1) diff --git a/ext/intl/timezone/timezone_class.cpp b/ext/intl/timezone/timezone_class.cpp index 2617b59a11bc8..c613edf5585f1 100644 --- a/ext/intl/timezone/timezone_class.cpp +++ b/ext/intl/timezone/timezone_class.cpp @@ -18,6 +18,7 @@ #endif #include "../intl_cppshims.h" +#include #include #include @@ -61,144 +62,144 @@ U_CFUNC void timezone_object_construct(const TimeZone *zone, zval *object, int o * Convert from TimeZone to DateTimeZone object */ U_CFUNC zval *timezone_convert_to_datetimezone(const TimeZone *timeZone, intl_error *outside_error, - const char *func, zval *ret) + zval *ret) { - UnicodeString id; - char *message = NULL; - php_timezone_obj *tzobj; - zval arg; + UnicodeString id; timeZone->getID(id); if (id.isBogus()) { - spprintf(&message, 0, "%s: could not obtain TimeZone id", func); intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); - goto error; + "could not obtain TimeZone id"); + return nullptr; } - object_init_ex(ret, php_date_get_timezone_ce()); - tzobj = Z_PHPTIMEZONE_P(ret); - if (id.compare(0, 3, UnicodeString("GMT", sizeof("GMT")-1, US_INV)) == 0) { /* The DateTimeZone constructor doesn't support offset time zones, - * so we must mess with DateTimeZone structure ourselves */ - tzobj->initialized = 1; + * so we must mess with DateTimeZone structure ourselves */ + object_init_ex(ret, php_date_get_timezone_ce()); + php_timezone_obj *tzobj = Z_PHPTIMEZONE_P(ret); + + tzobj->initialized = true; tzobj->type = TIMELIB_ZONETYPE_OFFSET; //convert offset from milliseconds to seconds tzobj->tzi.utc_offset = timeZone->getRawOffset() / 1000; } else { - zend_string *u8str; - /* Call the constructor! */ - u8str = intl_charFromString(id, &INTL_ERROR_CODE(*outside_error)); + zend_string *u8str = intl_charFromString(id, &INTL_ERROR_CODE(*outside_error)); if (!u8str) { - spprintf(&message, 0, "%s: could not convert id to UTF-8", func); intl_errors_set(outside_error, INTL_ERROR_CODE(*outside_error), - message, 1); - goto error; + "could not convert id to UTF-8"); + return nullptr; } + + zval arg; ZVAL_STR(&arg, u8str); - zend_call_known_instance_method_with_1_params( - Z_OBJCE_P(ret)->constructor, Z_OBJ_P(ret), NULL, &arg); - if (EG(exception)) { - spprintf(&message, 0, - "%s: DateTimeZone constructor threw exception", func); - intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR, - message, 1); - zend_object_store_ctor_failed(Z_OBJ_P(ret)); - zval_ptr_dtor(&arg); - goto error; - } + /* Instantiate the object and call the constructor */ + zend_result status = object_init_with_constructor(ret, php_date_get_timezone_ce(), 1, &arg, nullptr); zval_ptr_dtor(&arg); - } - - if (0) { -error: - if (ret) { - zval_ptr_dtor(ret); + if (UNEXPECTED(status == FAILURE)) { + zend_throw_exception(IntlException_ce_ptr, "DateTimeZone constructor threw exception", 0); + return nullptr; } - ret = NULL; } - if (message) { - efree(message); - } return ret; } /* }}} */ +static void timezone_throw_exception_with_call_location(const char *msg, const char *add_info) +{ + zend_string *fn = get_active_function_or_method_name(); + zend_throw_error(IntlException_ce_ptr, "%s(): %s%s%s%s", + ZSTR_VAL(fn), msg, + add_info ? "\"" : "", + add_info ? add_info : "", + add_info ? "\"" : "" + ); + zend_string_release_ex(fn, false); +} + /* {{{ timezone_process_timezone_argument - * TimeZone argument processor. outside_error may be NULL (for static functions/constructors) */ -U_CFUNC TimeZone *timezone_process_timezone_argument(zval *zv_timezone, - intl_error *outside_error, - const char *func) + * TimeZone argument processor. outside_error may be nullptr (for static functions/constructors) */ +U_CFUNC TimeZone *timezone_process_timezone_argument( + zend_object *timezone_object, zend_string *timezone_string, intl_error *outside_error) { - zval local_zv_tz; - TimeZone *timeZone; + std::unique_ptr timeZone; + bool free_string = false; - if (zv_timezone == NULL || Z_TYPE_P(zv_timezone) == IS_NULL) { + if (timezone_object == nullptr && timezone_string == nullptr) { timelib_tzinfo *tzinfo = get_timezone_info(); - ZVAL_STRING(&local_zv_tz, tzinfo->name); - zv_timezone = &local_zv_tz; - } else { - ZVAL_NULL(&local_zv_tz); + timezone_string = zend_string_init(tzinfo->name, strlen(tzinfo->name), false); + free_string = true; } - if (Z_TYPE_P(zv_timezone) == IS_OBJECT && - instanceof_function(Z_OBJCE_P(zv_timezone), TimeZone_ce_ptr)) { - TimeZone_object *to = Z_INTL_TIMEZONE_P(zv_timezone); - - if (to->utimezone == NULL) { - zend_throw_error(IntlException_ce_ptr, "%s: passed IntlTimeZone is not " - "properly constructed", func); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; - } - timeZone = to->utimezone->clone(); - if (UNEXPECTED(timeZone == NULL)) { - zend_throw_error(IntlException_ce_ptr, "%s: could not clone TimeZone", func); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; + if (timezone_object != nullptr) { + if (instanceof_function(timezone_object->ce, TimeZone_ce_ptr)) { + const TimeZone_object *to = php_intl_timezone_fetch_object(timezone_object); + + if (UNEXPECTED(to->utimezone == nullptr)) { + timezone_throw_exception_with_call_location( + "passed IntlTimeZone is not properly constructed",nullptr); + return nullptr; + } + timeZone = std::unique_ptr(to->utimezone->clone()); + if (UNEXPECTED(timeZone == nullptr)) { + timezone_throw_exception_with_call_location("could not clone TimeZone", nullptr); + return nullptr; + } + // well, this is included by the centralized C intl part so the "smart" part can't go further + return timeZone.release(); + } else if (instanceof_function(timezone_object->ce, php_date_get_timezone_ce())) { + php_timezone_obj *tz_obj = php_timezone_obj_from_obj(timezone_object); + + return timezone_convert_datetimezone(tz_obj->type, tz_obj, false, outside_error); + } else { + zval tmp; + zend_result status = timezone_object->handlers->cast_object(timezone_object, &tmp, IS_STRING); + if (EXPECTED(status == SUCCESS)) { + timezone_string = Z_STR(tmp); + free_string = true; + } else { + if (!EG(exception)) { + // TODO Proper type error + zend_throw_error(nullptr, "Object of class %s could not be converted to string", ZSTR_VAL(timezone_object->ce->name)); + } + return nullptr; + } } - } else if (Z_TYPE_P(zv_timezone) == IS_OBJECT && - instanceof_function(Z_OBJCE_P(zv_timezone), php_date_get_timezone_ce())) { + } - php_timezone_obj *tzobj = Z_PHPTIMEZONE_P(zv_timezone); + ZEND_ASSERT(timezone_string != nullptr); + UnicodeString id; + UErrorCode status = U_ZERO_ERROR; /* outside_error may be nullptr */ - zval_ptr_dtor_str(&local_zv_tz); - return timezone_convert_datetimezone(tzobj->type, tzobj, 0, - outside_error, func); - } else { - UnicodeString id; - UErrorCode status = U_ZERO_ERROR; /* outside_error may be NULL */ - if (!try_convert_to_string(zv_timezone)) { - zval_ptr_dtor_str(&local_zv_tz); - return NULL; - } - if (intl_stringFromChar(id, Z_STRVAL_P(zv_timezone), Z_STRLEN_P(zv_timezone), - &status) == FAILURE) { - zend_throw_error(IntlException_ce_ptr, "%s: Time zone identifier given is not a " - "valid UTF-8 string", func); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; + if (UNEXPECTED(intl_stringFromChar(id, ZSTR_VAL(timezone_string), ZSTR_LEN(timezone_string), &status) == FAILURE)) { + timezone_throw_exception_with_call_location("Time zone identifier given is not a valid UTF-8 string", nullptr); + if (free_string) { + zend_string_release_ex(timezone_string, false); } - timeZone = TimeZone::createTimeZone(id); - if (UNEXPECTED(timeZone == NULL)) { - zend_throw_error(IntlException_ce_ptr, "%s: Could not create time zone", func); - zval_ptr_dtor_str(&local_zv_tz); - return NULL; + return nullptr; + } + + timeZone = std::unique_ptr(TimeZone::createTimeZone(id)); + if (UNEXPECTED(timeZone == nullptr)) { + timezone_throw_exception_with_call_location("Could not create time zone",nullptr); + if (free_string) { + zend_string_release_ex(timezone_string, false); } - if (*timeZone == TimeZone::getUnknown()) { - zend_throw_error(IntlException_ce_ptr, "%s: No such time zone: '%s'", - func, Z_STRVAL_P(zv_timezone)); - zval_ptr_dtor_str(&local_zv_tz); - delete timeZone; - return NULL; + return nullptr; + } + if (UNEXPECTED(*timeZone == TimeZone::getUnknown())) { + timezone_throw_exception_with_call_location("No such time zone: ", ZSTR_VAL(timezone_string)); + if (free_string) { + zend_string_release_ex(timezone_string, false); } + return nullptr; } - - zval_ptr_dtor_str(&local_zv_tz); - - return timeZone; + if (free_string) { + zend_string_release_ex(timezone_string, false); + } + // well, this is included by the centralized C intl part so the "smart" part can't go further + return timeZone.release(); } /* }}} */ diff --git a/ext/intl/timezone/timezone_class.h b/ext/intl/timezone/timezone_class.h index 16d56b9af12df..bbfd8adcae23e 100644 --- a/ext/intl/timezone/timezone_class.h +++ b/ext/intl/timezone/timezone_class.h @@ -36,6 +36,8 @@ typedef struct { intl_error err; // ICU TimeZone + // TODO?: a direct change isn't possible due to C inclusion (also it s a const) + // but see later it can be made possible through different ICU class usages const TimeZone *utimezone; //whether to delete the timezone on object free @@ -64,8 +66,8 @@ static inline TimeZone_object *php_intl_timezone_fetch_object(zend_object *obj) RETURN_THROWS(); \ } -zval *timezone_convert_to_datetimezone(const TimeZone *timeZone, intl_error *outside_error, const char *func, zval *ret); -TimeZone *timezone_process_timezone_argument(zval *zv_timezone, intl_error *error, const char *func); +zval *timezone_convert_to_datetimezone(const TimeZone *timeZone, intl_error *outside_error, zval *ret); +TimeZone *timezone_process_timezone_argument(zend_object *timezone_object, zend_string *timezone_string, intl_error *error); void timezone_object_construct(const TimeZone *zone, zval *object, int owned); diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp index 6ff0cf5137790..3de186a9ca031 100644 --- a/ext/intl/timezone/timezone_methods.cpp +++ b/ext/intl/timezone/timezone_methods.cpp @@ -60,7 +60,7 @@ U_CFUNC PHP_FUNCTION(intltz_create_time_zone) UnicodeString id = UnicodeString(); if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_NULL(); } @@ -82,14 +82,11 @@ U_CFUNC PHP_FUNCTION(intltz_from_date_time_zone) tzobj = Z_PHPTIMEZONE_P(zv_timezone); if (!tzobj->initialized) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "DateTimeZone object is unconstructed", - 0); - RETURN_NULL(); + zend_throw_error(NULL, "DateTimeZone object is unconstructed"); + RETURN_THROWS(); } - tz = timezone_convert_datetimezone(tzobj->type, tzobj, false, NULL, - "intltz_from_date_time_zone"); + tz = timezone_convert_datetimezone(tzobj->type, tzobj, false, NULL); if (tz == NULL) { RETURN_NULL(); } @@ -127,62 +124,36 @@ U_CFUNC PHP_FUNCTION(intltz_get_unknown) U_CFUNC PHP_FUNCTION(intltz_create_enumeration) { - zval *arg = NULL; - StringEnumeration *se = NULL; - intl_error_reset(NULL); + zend_string *timezone = nullptr; + zend_long timezone_shift = 0; + bool is_null = true; + StringEnumeration *se = nullptr; + intl_error_reset(nullptr); /* double indirection to have the zend engine destroy the new zval that * results from separation */ ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(arg) + Z_PARAM_STR_OR_LONG_OR_NULL(timezone, timezone_shift, is_null) ZEND_PARSE_PARAMETERS_END(); - if (arg == NULL || Z_TYPE_P(arg) == IS_NULL) { + if (is_null) { se = TimeZone::createEnumeration(); - } else if (Z_TYPE_P(arg) == IS_LONG) { -int_offset: - if (UNEXPECTED(Z_LVAL_P(arg) < (zend_long)INT32_MIN || - Z_LVAL_P(arg) > (zend_long)INT32_MAX)) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "value is out of range", 0); - RETURN_FALSE; - } else { - se = TimeZone::createEnumeration((int32_t) Z_LVAL_P(arg)); - } - } else if (Z_TYPE_P(arg) == IS_DOUBLE) { -double_offset: - convert_to_long(arg); - goto int_offset; - } else if (Z_TYPE_P(arg) == IS_OBJECT || Z_TYPE_P(arg) == IS_STRING) { - zend_long lval; - double dval; - if (!try_convert_to_string(arg)) { + } else if (timezone != nullptr) { + se = TimeZone::createEnumeration(ZSTR_VAL(timezone)); + } else { + if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(timezone_shift))) { + zend_argument_value_error(1, "must be between %d and %d", INT32_MIN, INT32_MAX); RETURN_THROWS(); } - switch (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &lval, &dval, 0)) { - case IS_DOUBLE: - zval_ptr_dtor(arg); - ZVAL_DOUBLE(arg, dval); - goto double_offset; - case IS_LONG: - zval_ptr_dtor(arg); - ZVAL_LONG(arg, lval); - goto int_offset; - } - /* else call string version */ - se = TimeZone::createEnumeration(Z_STRVAL_P(arg)); - } else { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "invalid argument type", 0); - RETURN_FALSE; + se = TimeZone::createEnumeration(static_cast(timezone_shift)); } if (se) { IntlIterator_from_StringEnumeration(se, return_value); } else { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "error obtaining enumeration", 0); + intl_error_set(nullptr, U_ILLEGAL_ARGUMENT_ERROR, + "error obtaining enumeration"); RETVAL_FALSE; } } @@ -201,7 +172,7 @@ U_CFUNC PHP_FUNCTION(intltz_count_equivalent_ids) UnicodeString id = UnicodeString(); if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_FALSE; } @@ -230,18 +201,17 @@ U_CFUNC PHP_FUNCTION(intltz_create_time_zone_id_enumeration) if (zoneType != UCAL_ZONE_TYPE_ANY && zoneType != UCAL_ZONE_TYPE_CANONICAL && zoneType != UCAL_ZONE_TYPE_CANONICAL_LOCATION) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "bad zone type", 0); - RETURN_FALSE; + zend_argument_value_error(1, "must be one of IntlTimeZone::TYPE_ANY," + " IntlTimeZone::TYPE_CANONICAL, or IntlTimeZone::TYPE_CANONICAL_LOCATION"); + RETURN_THROWS(); } if (!arg3isnull) { - if (UNEXPECTED(offset_arg < (zend_long)INT32_MIN || offset_arg > (zend_long)INT32_MAX)) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "offset out of bounds", 0); - RETURN_FALSE; + if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(offset_arg))) { + zend_argument_value_error(3, "must be between %d and %d", INT32_MIN, INT32_MAX); + RETURN_THROWS(); } - offset = (int32_t)offset_arg; + offset = static_cast(offset_arg); offsetp = &offset; } //else leave offsetp NULL @@ -271,7 +241,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_canonical_id) UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_FALSE; } @@ -305,7 +275,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_region) UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_FALSE; } @@ -340,15 +310,16 @@ U_CFUNC PHP_FUNCTION(intltz_get_equivalent_id) Z_PARAM_LONG(index) ZEND_PARSE_PARAMETERS_END(); - if (UNEXPECTED(index < (zend_long)INT32_MIN || index > (zend_long)INT32_MAX)) { - RETURN_FALSE; + if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(index))) { + zend_argument_value_error(2, "must be between %d and %d", INT32_MIN, INT32_MAX); + RETURN_THROWS(); } UErrorCode status = UErrorCode(); UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_FALSE; } @@ -375,7 +346,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_iana_id) UnicodeString id; if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) { intl_error_set(NULL, status, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_FALSE; } @@ -484,8 +455,7 @@ U_CFUNC PHP_FUNCTION(intltz_has_same_rules) TIMEZONE_METHOD_FETCH_OBJECT; other_to = Z_INTL_TIMEZONE_P(other_object); if (other_to->utimezone == NULL) { - intl_errors_set(&to->err, U_ILLEGAL_ARGUMENT_ERROR, - "The second IntlTimeZone is unconstructed", 0); + intl_errors_set(&to->err, U_ILLEGAL_ARGUMENT_ERROR, "The second IntlTimeZone is unconstructed"); RETURN_FALSE; } @@ -519,8 +489,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_display_name) found = true; } if (!found) { - intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "wrong display type", 0); + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "wrong display type"); RETURN_FALSE; } @@ -567,7 +536,7 @@ U_CFUNC PHP_FUNCTION(intltz_to_date_time_zone) TIMEZONE_METHOD_FETCH_OBJECT; zval *ret = timezone_convert_to_datetimezone(to->utimezone, - &TIMEZONE_ERROR(to), "intltz_to_date_time_zone", &tmp); + &TIMEZONE_ERROR(to), &tmp); if (ret) { ZVAL_COPY_VALUE(return_value, ret); @@ -630,16 +599,16 @@ U_CFUNC PHP_FUNCTION(intltz_get_windows_id) error = U_ZERO_ERROR; if (intl_stringFromChar(uID, id->val, id->len, &error) == FAILURE) { intl_error_set(NULL, error, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_FALSE; } error = U_ZERO_ERROR; TimeZone::getWindowsID(uID, uWinID, error); - INTL_CHECK_STATUS(error, "intltz_get_windows_id: Unable to get timezone from windows ID"); + INTL_CHECK_STATUS(error, "Unable to get timezone from windows ID"); if (uWinID.length() == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "unknown system timezone", 0); + "unknown system timezone"); RETURN_FALSE; } @@ -668,7 +637,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_id_for_windows_id) error = U_ZERO_ERROR; if (intl_stringFromChar(uWinID, winID->val, winID->len, &error) == FAILURE) { intl_error_set(NULL, error, - "could not convert time zone id to UTF-16", 0); + "could not convert time zone id to UTF-16"); RETURN_FALSE; } @@ -677,7 +646,7 @@ U_CFUNC PHP_FUNCTION(intltz_get_id_for_windows_id) INTL_CHECK_STATUS(error, "unable to get windows ID for timezone"); if (uID.length() == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, - "unknown windows timezone", 0); + "unknown windows timezone"); RETURN_FALSE; } diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c index ff3ddf5161377..9c1f48608cf21 100644 --- a/ext/intl/transliterator/transliterator_methods.c +++ b/ext/intl/transliterator/transliterator_methods.c @@ -48,7 +48,7 @@ static int create_transliterator( char *str_id, size_t str_id_len, zend_long dir if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) { intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) ); - intl_error_set_custom_msg( NULL, "String conversion of id to UTF-16 failed", 0 ); + intl_error_set_custom_msg( NULL, "String conversion of id to UTF-16 failed"); zval_ptr_dtor( object ); return FAILURE; } @@ -64,15 +64,14 @@ static int create_transliterator( char *str_id, size_t str_id_len, zend_long dir { char *buf = NULL; intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) ); - spprintf( &buf, 0, "transliterator_create: unable to open ICU transliterator" + spprintf( &buf, 0, "unable to open ICU transliterator" " with id \"%s\"", str_id ); if( buf == NULL ) { - intl_error_set_custom_msg( NULL, - "transliterator_create: unable to open ICU transliterator", 0 ); + intl_error_set_custom_msg(NULL, "unable to open ICU transliterator"); } else { - intl_error_set_custom_msg( NULL, buf, /* copy message */ 1 ); + intl_error_set_custom_msg(NULL, buf); efree( buf ); } zval_ptr_dtor( object ); @@ -84,8 +83,7 @@ static int create_transliterator( char *str_id, size_t str_id_len, zend_long dir if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) { intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) ); - intl_error_set_custom_msg( NULL, - "transliterator_create: internal constructor call failed", 0 ); + intl_error_set_custom_msg(NULL, "internal constructor call failed"); zval_ptr_dtor( object ); return FAILURE; } @@ -169,12 +167,12 @@ PHP_FUNCTION( transliterator_create_from_rules ) char *msg = NULL; smart_str parse_error_str; parse_error_str = intl_parse_error_to_string( &parse_error ); - spprintf( &msg, 0, "transliterator_create_from_rules: unable to " + spprintf( &msg, 0, "unable to " "create ICU transliterator from rules (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "" ); smart_str_free( &parse_error_str ); if( msg != NULL ) { - intl_errors_set_custom_msg( INTL_DATA_ERROR_P( to ), msg, 1 ); + intl_errors_set_custom_msg( INTL_DATA_ERROR_P( to ), msg); efree( msg ); } zval_ptr_dtor( return_value ); @@ -182,7 +180,7 @@ PHP_FUNCTION( transliterator_create_from_rules ) } transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) ); /* no need to close the transliterator manually on construction error */ - INTL_METHOD_CHECK_STATUS_OR_NULL( to, "transliterator_create_from_rules: internal constructor call failed" ); + INTL_METHOD_CHECK_STATUS_OR_NULL( to, "internal constructor call failed" ); } /* }}} */ @@ -207,11 +205,11 @@ PHP_FUNCTION( transliterator_create_inverse ) TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* change "to" into new object (from "object" ) */ utrans = utrans_openInverse( to_orig->utrans, TRANSLITERATOR_ERROR_CODE_P( to ) ); - INTL_METHOD_CHECK_STATUS_OR_NULL( to, "transliterator_create_inverse: could not create " + INTL_METHOD_CHECK_STATUS_OR_NULL( to, "could not create " "inverse ICU transliterator" ); transliterator_object_construct( object, utrans, TRANSLITERATOR_ERROR_CODE_P( to ) ); /* no need to close the transliterator manually on construction error */ - INTL_METHOD_CHECK_STATUS_OR_NULL( to, "transliterator_create: internal constructor call failed" ); + INTL_METHOD_CHECK_STATUS_OR_NULL( to, "internal constructor call failed" ); } /* }}} */ @@ -229,7 +227,7 @@ PHP_FUNCTION( transliterator_list_ids ) en = utrans_openIDs( &status ); INTL_CHECK_STATUS( status, - "transliterator_list_ids: Failed to obtain registered transliterators" ); + "Failed to obtain registered transliterators" ); array_init( return_value ); while( (elem = uenum_unext( en, &elem_len, &status )) ) @@ -252,8 +250,8 @@ PHP_FUNCTION( transliterator_list_ids ) { zend_array_destroy( Z_ARR_P(return_value) ); RETVAL_FALSE; - intl_error_set_custom_msg( NULL, "transliterator_list_ids: " - "Failed to build array of registered transliterators", 0 ); + intl_error_set_custom_msg( NULL, + "Failed to build array of registered transliterators"); } } /* }}} */ @@ -342,13 +340,12 @@ PHP_FUNCTION( transliterator_transliterate ) { char *msg; spprintf( &msg, 0, - "transliterator_transliterate: Neither \"start\" nor the \"end\" " + "Neither \"start\" nor the \"end\" " "arguments can exceed the number of UTF-16 code units " "(in this case, %d)", (int) ustr_len ); if(msg != NULL ) { - intl_errors_set( TRANSLITERATOR_ERROR_P( to ), U_ILLEGAL_ARGUMENT_ERROR, - msg, 1 ); + intl_errors_set(TRANSLITERATOR_ERROR_P(to), U_ILLEGAL_ARGUMENT_ERROR, msg); efree( msg ); } goto cleanup; @@ -384,8 +381,7 @@ PHP_FUNCTION( transliterator_transliterate ) else if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) ) { intl_error_set_code( NULL, TRANSLITERATOR_ERROR_CODE( to ) ); - intl_errors_set_custom_msg( TRANSLITERATOR_ERROR_P( to ), - "transliterator_transliterate: transliteration failed", 0 ); + intl_errors_set_custom_msg( TRANSLITERATOR_ERROR_P( to ), "transliteration failed"); goto cleanup; } else diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.cpp similarity index 96% rename from ext/intl/uchar/uchar.c rename to ext/intl/uchar/uchar.cpp index ecfcd8fbe624a..f1f777f0ea3eb 100644 --- a/ext/intl/uchar/uchar.c +++ b/ext/intl/uchar/uchar.cpp @@ -1,3 +1,4 @@ +extern "C" { #include "uchar.h" #include "intl_data.h" #include "intl_convert.h" @@ -6,6 +7,7 @@ #include #include "uchar_arginfo.h" +} #define IC_METHOD(mname) PHP_METHOD(IntlChar, mname) @@ -16,21 +18,21 @@ static inline int convert_cp(UChar32* pcp, zend_string *string_codepoint, zend_l if (ZEND_SIZE_T_INT_OVFL(string_codepoint_length)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Input string is too long.", 0); + intl_error_set_custom_msg(NULL, "Input string is too long."); return FAILURE; } U8_NEXT(ZSTR_VAL(string_codepoint), i, string_codepoint_length, int_codepoint); if ((size_t)i != string_codepoint_length) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Passing a UTF-8 character for codepoint requires a string which is exactly one UTF-8 codepoint long.", 0); + intl_error_set_custom_msg(NULL, "Passing a UTF-8 character for codepoint requires a string which is exactly one UTF-8 codepoint long."); return FAILURE; } } if ((int_codepoint < UCHAR_MIN_VALUE) || (int_codepoint > UCHAR_MAX_VALUE)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Codepoint out of range", 0); + intl_error_set_custom_msg(NULL, "Codepoint out of range"); return FAILURE; } *pcp = (UChar32)int_codepoint; @@ -181,7 +183,7 @@ static UBool enumCharType_callback(enumCharType_data *context, if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) { intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR); - intl_errors_set_custom_msg(NULL, "enumCharTypes callback failed", 0); + intl_errors_set_custom_msg(NULL, "enumCharTypes callback failed"); zval_ptr_dtor(&retval); return 0; } @@ -284,7 +286,7 @@ static UBool enumCharNames_callback(enumCharNames_data *context, if (zend_call_function(&context->fci, &context->fci_cache) == FAILURE) { intl_error_set_code(NULL, U_INTERNAL_PROGRAM_ERROR); - intl_error_set_custom_msg(NULL, "enumCharNames callback failed", 0); + intl_error_set_custom_msg(NULL, "enumCharNames callback failed"); zval_ptr_dtor(&retval); zval_ptr_dtor_str(&args[2]); return 0; @@ -314,7 +316,7 @@ IC_METHOD(enumCharNames) { RETURN_FALSE; } - u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, nameChoice, &error); + u_enumCharNames(start, limit, (UEnumCharNamesFn*)enumCharNames_callback, &context, static_cast(nameChoice), &error); INTL_CHECK_STATUS(error, NULL); RETURN_TRUE; } @@ -337,7 +339,7 @@ IC_METHOD(getPropertyName) { RETURN_STRING(ret); } else { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Failed to get property name", 0); + intl_error_set_custom_msg(NULL, "Failed to get property name"); RETURN_FALSE; } } @@ -373,7 +375,7 @@ IC_METHOD(getPropertyValueName) { RETURN_STRING(ret); } else { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Failed to get property name", 0); + intl_error_set_custom_msg(NULL, "Failed to get property name"); RETURN_FALSE; } } @@ -445,7 +447,7 @@ IC_METHOD(digit) { ret = u_digit(cp, radix); if (ret < 0) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); - intl_error_set_custom_msg(NULL, "Invalid digit", 0); + intl_error_set_custom_msg(NULL, "Invalid digit"); RETURN_FALSE; } RETURN_LONG(ret); @@ -515,7 +517,7 @@ IC_METHOD(getFC_NFKC_Closure) { if (closure_len == 0) { RETURN_EMPTY_STRING(); } - closure = safe_emalloc(sizeof(UChar), closure_len + 1, 0); + closure = reinterpret_cast(safe_emalloc(sizeof(UChar), closure_len + 1, 0)); error = U_ZERO_ERROR; closure_len = u_getFC_NFKC_Closure(cp, closure, closure_len, &error); if (U_FAILURE(error)) { diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index c147b8eb23d73..a73277915405d 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -41,18 +41,6 @@ static zend_always_inline bool php_json_check_stack_limit(void) #endif } -static int php_json_determine_array_type(zval *val) /* {{{ */ -{ - zend_array *myht = Z_ARRVAL_P(val); - - if (myht) { - return zend_array_is_list(myht) ? PHP_JSON_OUTPUT_ARRAY : PHP_JSON_OUTPUT_OBJECT; - } - - return PHP_JSON_OUTPUT_ARRAY; -} -/* }}} */ - /* {{{ Pretty printing support functions */ static inline void php_json_pretty_print_char(smart_str *buf, int options, char c) /* {{{ */ @@ -63,12 +51,10 @@ static inline void php_json_pretty_print_char(smart_str *buf, int options, char } /* }}} */ -static inline void php_json_pretty_print_indent(smart_str *buf, int options, php_json_encoder *encoder) /* {{{ */ +static inline void php_json_pretty_print_indent(smart_str *buf, int options, const php_json_encoder *encoder) /* {{{ */ { - int i; - if (options & PHP_JSON_PRETTY_PRINT) { - for (i = 0; i < encoder->depth; ++i) { + for (int i = 0; i < encoder->depth; ++i) { smart_str_appendl(buf, " ", 4); } } @@ -122,7 +108,8 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options) static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */ { - int r, need_comma = 0; + bool encode_as_object = options & PHP_JSON_FORCE_OBJECT; + bool need_comma = false; HashTable *myht, *prop_ht; zend_refcounted *recursion_rc; @@ -138,7 +125,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, myht = Z_ARRVAL_P(val); recursion_rc = (zend_refcounted *)myht; prop_ht = NULL; - r = (options & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : php_json_determine_array_type(val); + encode_as_object = encode_as_object || !zend_array_is_list(myht); } else if (Z_OBJ_P(val)->properties == NULL && Z_OBJ_HT_P(val)->get_properties_for == NULL && Z_OBJ_HT_P(val)->get_properties == zend_std_get_properties @@ -146,9 +133,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, && !zend_object_is_lazy(Z_OBJ_P(val))) { /* Optimized version without rebuilding properties HashTable */ zend_object *obj = Z_OBJ_P(val); - zend_class_entry *ce = obj->ce; - zend_property_info *prop_info; - zval *prop; + const zend_class_entry *ce = obj->ce; if (GC_IS_RECURSIVE(obj)) { encoder->error_code = PHP_JSON_ERROR_RECURSION; @@ -163,7 +148,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, ++encoder->depth; for (int i = 0; i < ce->default_properties_count; i++) { - prop_info = ce->properties_info_table[i]; + zend_property_info *prop_info = ce->properties_info_table[i]; if (!prop_info) { continue; } @@ -171,7 +156,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, /* Skip protected and private members. */ continue; } - prop = OBJ_PROP(obj, prop_info->offset); + zval *prop = OBJ_PROP(obj, prop_info->offset); if (Z_TYPE_P(prop) == IS_UNDEF) { continue; } @@ -228,7 +213,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, * referenced from a different place in the object graph. */ recursion_rc = (zend_refcounted *)obj; } - r = PHP_JSON_OUTPUT_OBJECT; + encode_as_object = true; } if (recursion_rc && GC_IS_RECURSIVE(recursion_rc)) { @@ -240,7 +225,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, PHP_JSON_HASH_PROTECT_RECURSION(recursion_rc); - if (r == PHP_JSON_OUTPUT_ARRAY) { + if (!encode_as_object) { smart_str_appendc(buf, '['); } else { smart_str_appendc(buf, '{'); @@ -259,7 +244,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, zval tmp; ZVAL_UNDEF(&tmp); - if (r == PHP_JSON_OUTPUT_ARRAY) { + if (!encode_as_object) { ZEND_ASSERT(Z_TYPE_P(data) != IS_PTR); if (need_comma) { @@ -270,7 +255,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, php_json_pretty_print_char(buf, options, '\n'); php_json_pretty_print_indent(buf, options, encoder); - } else if (r == PHP_JSON_OUTPUT_OBJECT) { + } else { if (key) { if (ZSTR_VAL(key)[0] == '\0' && ZSTR_LEN(key) > 0 && Z_TYPE_P(val) == IS_OBJECT) { /* Skip protected and private members. */ @@ -354,7 +339,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, php_json_pretty_print_indent(buf, options, encoder); } - if (r == PHP_JSON_OUTPUT_ARRAY) { + if (!encode_as_object) { smart_str_appendc(buf, ']'); } else { smart_str_appendc(buf, '}'); @@ -369,7 +354,6 @@ zend_result php_json_escape_string( smart_str *buf, const char *s, size_t len, int options, php_json_encoder *encoder) /* {{{ */ { - unsigned int us; size_t pos, checkpoint; char *dst; @@ -407,7 +391,7 @@ zend_result php_json_escape_string( 0xffffffff, 0x500080c4, 0x10000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; - us = (unsigned char)s[pos]; + unsigned int us = (unsigned char)s[pos]; if (EXPECTED(!ZEND_BIT_TEST(charmap, us))) { pos++; len--; @@ -626,7 +610,7 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zend_obje static zend_result php_json_encode_serializable_enum(smart_str *buf, zval *val, int options, php_json_encoder *encoder) { - zend_class_entry *ce = Z_OBJCE_P(val); + const zend_class_entry *ce = Z_OBJCE_P(val); if (ce->enum_backing_type == IS_UNDEF) { encoder->error_code = PHP_JSON_ERROR_NON_BACKED_ENUM; smart_str_appendc(buf, '0'); diff --git a/ext/json/php_json.h b/ext/json/php_json.h index 00c87eca53c9e..b79c7c836f7a3 100644 --- a/ext/json/php_json.h +++ b/ext/json/php_json.h @@ -79,10 +79,6 @@ typedef enum { #define PHP_JSON_INVALID_UTF8_SUBSTITUTE (1<<21) #define PHP_JSON_THROW_ON_ERROR (1<<22) -/* Internal flags */ -#define PHP_JSON_OUTPUT_ARRAY 0 -#define PHP_JSON_OUTPUT_OBJECT 1 - /* default depth */ #define PHP_JSON_PARSER_DEFAULT_DEPTH 512 diff --git a/ext/ldap/config.m4 b/ext/ldap/config.m4 index 7d0229f6868c4..ae0ae7fba9598 100644 --- a/ext/ldap/config.m4 +++ b/ext/ldap/config.m4 @@ -60,15 +60,20 @@ if test "$PHP_LDAP" != "no"; then [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) AS_VAR_IF([PHP_LDAP], [yes], [ - PKG_CHECK_MODULES([LDAP], [lber ldap]) - PHP_LDAP_PKGCONFIG=true - ], [PHP_LDAP_CHECKS([$PHP_LDAP])]) + PKG_CHECK_MODULES([LDAP], [lber ldap], + PHP_LDAP_PKGCONFIG=true, PHP_LDAP_PKGCONFIG=false)]) AS_IF([test "$PHP_LDAP_PKGCONFIG" = true], [ PHP_EVAL_INCLINE([$LDAP_CFLAGS]) PHP_EVAL_LIBLINE([$LDAP_LIBS], [LDAP_SHARED_LIBADD]) ], [ - AS_VAR_IF([LDAP_DIR],, [AC_MSG_ERROR([Cannot find ldap.h])]) + AS_VAR_IF([PHP_LDAP], [yes], [ + for i in /usr/local /usr; do + PHP_LDAP_CHECKS([$i]) + done + ], [PHP_LDAP_CHECKS([$PHP_LDAP])]) + AC_MSG_CHECKING([for ldap.h]) + AS_VAR_IF([LDAP_DIR],, [AC_MSG_ERROR([Cannot find ldap.h])], AC_MSG_RESULT([$LDAP_DIR])) dnl -pc removal is a hack for clang MACHINE_INCLUDES=$($CC -dumpmachine | $SED 's/-pc//') diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 0e9f953a2a2a4..42b9249721e79 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -32,7 +32,6 @@ #include -#include "ext/standard/dl.h" #include "php_ldap.h" #ifdef PHP_WIN32 @@ -278,7 +277,7 @@ static void php_ldap_zend_string_release_from_char_pointer(char *ptr) { } /* {{{ Parse controls from and to arrays */ -static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, int request) +static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, bool request) { array_init(array); @@ -292,10 +291,10 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) { int expire = 0, grace = 0, rc; LDAPPasswordPolicyError pperr; - zval value; rc = ldap_parse_passwordpolicy_control(ld, ctrl, &expire, &grace, &pperr); if ( rc == LDAP_SUCCESS ) { + zval value; array_init(&value); add_assoc_long(&value, "expire", expire); add_assoc_long(&value, "grace", grace); @@ -310,7 +309,6 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { int lestimated, rc; struct berval lcookie = { 0L, NULL }; - zval value; if (ctrl->ldctl_value.bv_len) { /* ldap_parse_pageresponse_control() allocates lcookie.bv_val */ @@ -321,6 +319,7 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, } if ( rc == LDAP_SUCCESS ) { + zval value; array_init(&value); add_assoc_long(&value, "size", lestimated); add_assoc_stringl(&value, "cookie", lcookie.bv_val, lcookie.bv_len); @@ -348,7 +347,6 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, add_assoc_stringl(&value, "dn", bv.bv_val, bv.bv_len); while (ber_scanf(ber, "{m" /*}*/, &bv) != LBER_ERROR) { - int i; BerVarray vals = NULL; zval tmp; @@ -358,7 +356,7 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, } array_init(&tmp); - for (i = 0; vals[i].bv_val != NULL; i++) { + for (int i = 0; vals[i].bv_val != NULL; i++) { add_next_index_stringl(&tmp, vals[i].bv_val, vals[i].bv_len); } add_assoc_zval(&value, bv.bv_val, &tmp); @@ -372,7 +370,6 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, ber_free(ber, 1); } } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_SORTRESPONSE) == 0) { - zval value; int errcode, rc; char* attribute; @@ -382,6 +379,7 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, rc = -1; } if ( rc == LDAP_SUCCESS ) { + zval value; array_init(&value); add_assoc_long(&value, "errcode", errcode); if (attribute) { @@ -395,7 +393,6 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_VLVRESPONSE) == 0) { int target, count, errcode, rc; struct berval *context; - zval value; if (ctrl->ldctl_value.bv_len) { rc = ldap_parse_vlvresponse_control(ld, ctrl, &target, &count, &context, &errcode); @@ -403,6 +400,7 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, rc = -1; } if ( rc == LDAP_SUCCESS ) { + zval value; array_init(&value); add_assoc_long(&value, "target", target); add_assoc_long(&value, "count", count); @@ -486,12 +484,11 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT } } else if (zend_string_equals_literal(control_oid, LDAP_CONTROL_ASSERT)) { zval* tmp; - zend_string* assert; if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) { rc = -1; zend_value_error("%s(): Control must have a \"filter\" key", get_active_function_name()); } else { - assert = zval_get_string(tmp); + zend_string* assert = zval_get_string(tmp); if (EG(exception)) { rc = -1; goto failure; @@ -544,15 +541,14 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT rc = -1; php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); } else { - int num_attribs, i; zval* attr; - num_attribs = zend_hash_num_elements(Z_ARRVAL_P(tmp)); + uint32_t num_attribs = zend_hash_num_elements(Z_ARRVAL_P(tmp)); ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0); tmpstrings1 = safe_emalloc(num_attribs, sizeof(zend_string*), 0); num_tmpstrings1 = 0; - for (i = 0; ilink, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); if (rc == -1) { php_error_docref(NULL, E_WARNING, "Bind operation failed"); @@ -1270,7 +1260,7 @@ PHP_FUNCTION(ldap_bind_ext) /* return a PHP control object */ object_init_ex(return_value, ldap_result_ce); - result = Z_LDAP_RESULT_P(return_value); + ldap_resultdata *result = Z_LDAP_RESULT_P(return_value); result->result = ldap_res; } @@ -1491,7 +1481,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) LDAPControl **lserverctrls = NULL; int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1; int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1; - int ret = 1, ldap_errno, argcount = ZEND_NUM_ARGS(); + bool has_errors = false; ZEND_PARSE_PARAMETERS_START(3, 9) Z_PARAM_ZVAL(link) @@ -1507,7 +1497,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ZEND_PARSE_PARAMETERS_END(); /* Reverse -> fall through */ - switch (argcount) { + switch (ZEND_NUM_ARGS()) { case 9: case 8: ldap_deref = deref; @@ -1546,13 +1536,13 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ZVAL_DEREF(attribute_zv); if (Z_TYPE_P(attribute_zv) != IS_STRING) { zend_argument_type_error(4, "must be a list of strings, %s given", zend_zval_value_name(attribute_zv)); - ret = 0; + has_errors = true; goto cleanup; } zend_string *attribute = Z_STR_P(attribute_zv); if (zend_str_has_nul_byte(attribute)) { zend_argument_value_error(4, "must not contain strings with any null bytes"); - ret = 0; + has_errors = true; goto cleanup; } ldap_attrs[attribute_index++] = ZSTR_VAL(attribute); @@ -1568,12 +1558,12 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) uint32_t num_links = zend_hash_num_elements(Z_ARRVAL_P(link)); if (num_links == 0) { zend_argument_must_not_be_empty_error(1); - ret = 0; + has_errors = true; goto cleanup; } if (!zend_array_is_list(Z_ARRVAL_P(link))) { zend_argument_value_error(1, "must be a list"); - ret = 0; + has_errors = true; goto cleanup; } @@ -1581,19 +1571,19 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (base_dn_ht) { if (!zend_array_is_list(base_dn_ht)) { zend_argument_value_error(2, "must be a list"); - ret = 0; + has_errors = true; goto cleanup; } num_base_dns = zend_hash_num_elements(base_dn_ht); if (num_base_dns != num_links) { zend_argument_value_error(2, "must be the same size as argument #1"); - ret = 0; + has_errors = true; goto cleanup; } } else { if (zend_str_has_nul_byte(base_dn_str)) { zend_argument_value_error(2, "must not contain null bytes"); - ret = 0; + has_errors = true; goto cleanup; } ldap_base_dn = base_dn_str; @@ -1603,19 +1593,19 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (filter_ht) { if (!zend_array_is_list(filter_ht)) { zend_argument_value_error(3, "must be a list"); - ret = 0; + has_errors = true; goto cleanup; } num_filters = zend_hash_num_elements(filter_ht); if (num_filters != num_links) { zend_argument_value_error(3, "must be the same size as argument #1"); - ret = 0; + has_errors = true; goto cleanup; } } else { if (zend_str_has_nul_byte(filter_str)) { zend_argument_value_error(3, "must not contain null bytes"); - ret = 0; + has_errors = true; goto cleanup; } ldap_filter = filter_str; @@ -1632,14 +1622,14 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ZVAL_DEREF(link_zv); if (Z_TYPE_P(link_zv) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(link_zv), ldap_link_ce)) { zend_argument_value_error(1, "must be a list of LDAP\\Connection"); - ret = 0; + has_errors = true; goto cleanup_parallel; } ldap_linkdata *current_ld = Z_LDAP_LINK_P(link_zv); if (!current_ld->link) { zend_throw_error(NULL, "LDAP connection has already been closed"); - ret = 0; + has_errors = true; goto cleanup_parallel; } @@ -1649,13 +1639,13 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ZVAL_DEREF(base_dn_zv); if (Z_TYPE_P(base_dn_zv) != IS_STRING) { zend_argument_type_error(2, "must be a list of strings, %s given", zend_zval_value_name(base_dn_zv)); - ret = 0; + has_errors = true; goto cleanup_parallel; } ldap_base_dn = Z_STR_P(base_dn_zv); if (zend_str_has_nul_byte(ldap_base_dn)) { zend_argument_value_error(2, "must not contain null bytes"); - ret = 0; + has_errors = true; goto cleanup_parallel; } } @@ -1665,13 +1655,13 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ZVAL_DEREF(filter_zv); if (Z_TYPE_P(filter_zv) != IS_STRING) { zend_argument_type_error(3, "must be a list of strings, %s given", zend_zval_value_name(filter_zv)); - ret = 0; + has_errors = true; goto cleanup_parallel; } ldap_filter = Z_STR_P(filter_zv); if (zend_str_has_nul_byte(ldap_filter)) { zend_argument_value_error(3, "must not contain null bytes"); - ret = 0; + has_errors = true; goto cleanup_parallel; } } @@ -1721,26 +1711,26 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ld = Z_LDAP_LINK_P(link); if (!ld->link) { zend_throw_error(NULL, "LDAP connection has already been closed"); - ret = 0; + has_errors = true; goto cleanup; } if (!base_dn_str) { zend_argument_type_error(2, "must be of type string when argument #1 ($ldap) is an LDAP\\Connection instance"); - ret = 0; + has_errors = true; goto cleanup; } if (!filter_str) { zend_argument_type_error(3, "must be of type string when argument #1 ($ldap) is an LDAP\\Connection instance"); - ret = 0; + has_errors = true; goto cleanup; } if (server_controls_ht) { lserverctrls = php_ldap_controls_from_array(ld->link, server_controls_ht, 9); if (lserverctrls == NULL) { - ret = 0; + has_errors = true; goto cleanup; } } @@ -1748,7 +1738,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref); /* Run the actual search */ - ldap_errno = ldap_search_ext_s(ld->link, ZSTR_VAL(base_dn_str), scope, ZSTR_VAL(filter_str), ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &ldap_res); + int ldap_errno = ldap_search_ext_s(ld->link, ZSTR_VAL(base_dn_str), scope, ZSTR_VAL(filter_str), ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &ldap_res); if (ldap_errno != LDAP_SUCCESS && ldap_errno != LDAP_SIZELIMIT_EXCEEDED @@ -1765,7 +1755,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ldap_msgfree(ldap_res); } php_error_docref(NULL, E_WARNING, "Search: %s", ldap_err2string(ldap_errno)); - ret = 0; + has_errors = true; } else { if (ldap_errno == LDAP_SIZELIMIT_EXCEEDED) { php_error_docref(NULL, E_WARNING, "Partial search results returned: Sizelimit exceeded"); @@ -1791,8 +1781,8 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (ldap_attrs != NULL) { efree(ldap_attrs); } - if (!ret) { - RETVAL_BOOL(ret); + if (has_errors) { + RETVAL_FALSE; } if (lserverctrls) { _php_ldap_controls_free(&lserverctrls); @@ -1866,7 +1856,6 @@ PHP_FUNCTION(ldap_first_entry) { zval *link, *result; ldap_linkdata *ld; - ldap_result_entry *resultentry; ldap_resultdata *ldap_result; LDAPMessage *entry; @@ -1884,7 +1873,7 @@ PHP_FUNCTION(ldap_first_entry) RETVAL_FALSE; } else { object_init_ex(return_value, ldap_result_entry_ce); - resultentry = Z_LDAP_RESULT_ENTRY_P(return_value); + ldap_result_entry *resultentry = Z_LDAP_RESULT_ENTRY_P(return_value); ZVAL_COPY(&resultentry->res, result); resultentry->data = entry; resultentry->ber = NULL; @@ -1897,7 +1886,7 @@ PHP_FUNCTION(ldap_next_entry) { zval *link, *result_entry; ldap_linkdata *ld; - ldap_result_entry *resultentry, *resultentry_next; + ldap_result_entry *resultentry; LDAPMessage *entry_next; if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) { @@ -1913,7 +1902,7 @@ PHP_FUNCTION(ldap_next_entry) RETVAL_FALSE; } else { object_init_ex(return_value, ldap_result_entry_ce); - resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value); + ldap_result_entry *resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value); ZVAL_COPY(&resultentry_next->res, &resultentry->res); resultentry_next->data = entry_next; resultentry_next->ber = NULL; @@ -1927,14 +1916,10 @@ PHP_FUNCTION(ldap_get_entries) zval *link, *result; ldap_resultdata *ldap_result; LDAPMessage *ldap_result_entry; - zval tmp1, tmp2; ldap_linkdata *ld; LDAP *ldap; - int num_entries, num_attrib, num_values, i; + int num_entries; BerElement *ber; - char *attribute; - size_t attr_len; - struct berval **ldap_value; char *dn; if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result, ldap_result_ce) != SUCCESS) { @@ -1965,23 +1950,25 @@ PHP_FUNCTION(ldap_get_entries) num_entries = 0; while (ldap_result_entry != NULL) { + zval tmp1; array_init(&tmp1); - num_attrib = 0; - attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber); + int num_attrib = 0; + char *attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber); while (attribute != NULL) { - ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute); - num_values = ldap_count_values_len(ldap_value); + struct berval **ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute); + int num_values = ldap_count_values_len(ldap_value); + zval tmp2; array_init(&tmp2); add_assoc_long(&tmp2, "count", num_values); - for (i = 0; i < num_values; i++) { + for (int i = 0; i < num_values; i++) { add_index_stringl(&tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len); } ldap_value_free_len(ldap_value); - attr_len = strlen(attribute); + size_t attr_len = strlen(attribute); zend_str_tolower(attribute, attr_len); zend_hash_str_update(Z_ARRVAL(tmp1), attribute, attr_len, &tmp2); add_index_string(&tmp1, num_attrib, attribute); @@ -2093,12 +2080,10 @@ PHP_FUNCTION(ldap_next_attribute) PHP_FUNCTION(ldap_get_attributes) { zval *link, *result_entry; - zval tmp; ldap_linkdata *ld; ldap_result_entry *resultentry; char *attribute; - struct berval **ldap_value; - int i, num_values, num_attrib; + int num_attrib; BerElement *ber; if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) { @@ -2115,12 +2100,13 @@ PHP_FUNCTION(ldap_get_attributes) attribute = ldap_first_attribute(ld->link, resultentry->data, &ber); while (attribute != NULL) { - ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute); - num_values = ldap_count_values_len(ldap_value); + struct berval **ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute); + int num_values = ldap_count_values_len(ldap_value); + zval tmp; array_init(&tmp); add_assoc_long(&tmp, "count", num_values); - for (i = 0; i < num_values; i++) { + for (int i = 0; i < num_values; i++) { add_index_stringl(&tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len); } ldap_value_free_len(ldap_value); @@ -2152,7 +2138,7 @@ PHP_FUNCTION(ldap_get_values_len) ldap_result_entry *resultentry; char *attr; struct berval **ldap_value_len; - int i, num_values; + int num_values; size_t attr_len; if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOp", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce, &attr, &attr_len) != SUCCESS) { @@ -2172,7 +2158,7 @@ PHP_FUNCTION(ldap_get_values_len) num_values = ldap_count_values_len(ldap_value_len); array_init(return_value); - for (i=0; ibv_val, ldap_value_len[i]->bv_len); } @@ -2267,7 +2253,7 @@ PHP_FUNCTION(ldap_dn2ufn) /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */ #define PHP_LD_FULL_ADD 0xff /* {{{ php_ldap_do_modify */ -static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) +static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, bool ext) { zval *link; ldap_linkdata *ld; @@ -2279,7 +2265,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) ldap_resultdata *result; LDAPMessage *ldap_res; size_t dn_len; - int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */ + bool is_full_add = false; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oph/|h!", &link, ldap_link_ce, &dn, &dn_len, &attributes_ht, &server_controls_ht) != SUCCESS) { RETURN_THROWS(); @@ -2301,7 +2287,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) /* added by gerrit thomson to fix ldap_add using ldap_mod_add */ if (oper == PHP_LD_FULL_ADD) { oper = LDAP_MOD_ADD; - is_full_add = 1; + is_full_add = true; } /* end additional , gerrit thomson */ @@ -2396,7 +2382,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) /* check flag to see if do_mod was called to perform full add , gerrit thomson */ int ldap_status_code = LDAP_SUCCESS; int msgid; - if (is_full_add == 1) { + if (is_full_add) { if (ext) { ldap_status_code = ldap_add_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid); } else { @@ -2469,14 +2455,14 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) PHP_FUNCTION(ldap_add) { /* use a newly define parameter into the do_modify so ldap_mod_add can be used the way it is supposed to be used , Gerrit THomson */ - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, false); } /* }}} */ /* {{{ Add entries to LDAP directory */ PHP_FUNCTION(ldap_add_ext) { - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, true); } /* }}} */ @@ -2485,54 +2471,52 @@ PHP_FUNCTION(ldap_add_ext) /* {{{ Replace attribute values with new ones */ PHP_FUNCTION(ldap_mod_replace) { - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 0); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, false); } /* }}} */ /* {{{ Replace attribute values with new ones */ PHP_FUNCTION(ldap_mod_replace_ext) { - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 1); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, true); } /* }}} */ /* {{{ Add attribute values to current */ PHP_FUNCTION(ldap_mod_add) { - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 0); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, false); } /* }}} */ /* {{{ Add attribute values to current */ PHP_FUNCTION(ldap_mod_add_ext) { - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, true); } /* }}} */ /* {{{ Delete attribute values */ PHP_FUNCTION(ldap_mod_del) { - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 0); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, false); } /* }}} */ /* {{{ Delete attribute values */ PHP_FUNCTION(ldap_mod_del_ext) { - php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, true); } /* }}} */ /* {{{ php_ldap_do_delete */ -static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext) +static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, bool ext) { zval *link; HashTable *server_controls_ht = NULL; ldap_linkdata *ld; LDAPControl **lserverctrls = NULL; - ldap_resultdata *result; - LDAPMessage *ldap_res; char *dn; int rc, msgid; size_t dn_len; @@ -2562,6 +2546,7 @@ static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext) RETVAL_FALSE; goto cleanup; } else if (ext) { + LDAPMessage *ldap_res; rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); if (rc == -1) { php_error_docref(NULL, E_WARNING, "Delete operation failed"); @@ -2571,7 +2556,7 @@ static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext) /* return a PHP control object */ object_init_ex(return_value, ldap_result_ce); - result = Z_LDAP_RESULT_P(return_value); + ldap_resultdata *result = Z_LDAP_RESULT_P(return_value); result->result = ldap_res; } else { RETVAL_TRUE; @@ -2589,14 +2574,14 @@ static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext) /* {{{ Delete an entry from a directory */ PHP_FUNCTION(ldap_delete) { - php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); } /* }}} */ /* {{{ Delete an entry from a directory */ PHP_FUNCTION(ldap_delete_ext) { - php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } /* }}} */ @@ -3148,7 +3133,7 @@ PHP_FUNCTION(ldap_get_option) } RETURN_FALSE; } - _php_ldap_controls_to_array(ldap, ctrls, retval, 1); + _php_ldap_controls_to_array(ldap, ctrls, retval, true); } break; /* options not implemented case LDAP_OPT_API_INFO: @@ -3342,7 +3327,6 @@ PHP_FUNCTION(ldap_set_option) case LDAP_OPT_CLIENT_CONTROLS: { LDAPControl **ctrls; - int rc; if (Z_TYPE_P(newval) != IS_ARRAY) { zend_argument_type_error(3, "must be of type array for the LDAP_OPT_CLIENT_CONTROLS option, %s given", zend_zval_value_name(newval)); @@ -3354,7 +3338,7 @@ PHP_FUNCTION(ldap_set_option) if (ctrls == NULL) { RETURN_FALSE; } else { - rc = ldap_set_option(ldap, option, ctrls); + int rc = ldap_set_option(ldap, option, ctrls); _php_ldap_controls_free(&ctrls); if (rc != LDAP_SUCCESS) { RETURN_FALSE; @@ -3377,7 +3361,7 @@ PHP_FUNCTION(ldap_parse_result) ldap_linkdata *ld; ldap_resultdata *ldap_result; LDAPControl **lserverctrls = NULL; - char **lreferrals, **refp; + char **lreferrals; char *lmatcheddn, *lerrmsg; int rc, lerrcode; @@ -3405,7 +3389,7 @@ PHP_FUNCTION(ldap_parse_result) ZEND_TRY_ASSIGN_REF_LONG(errcode, lerrcode); if (serverctrls) { - _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0); + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, false); } if (referrals) { referrals = zend_try_array_init(referrals); @@ -3413,7 +3397,7 @@ PHP_FUNCTION(ldap_parse_result) RETURN_THROWS(); } if (lreferrals != NULL) { - refp = lreferrals; + char **refp = lreferrals; while (*refp) { add_next_index_string(referrals, *refp); refp++; @@ -3526,7 +3510,6 @@ PHP_FUNCTION(ldap_first_reference) { zval *link, *result; ldap_linkdata *ld; - ldap_result_entry *resultentry; ldap_resultdata *ldap_result; LDAPMessage *entry; @@ -3544,7 +3527,7 @@ PHP_FUNCTION(ldap_first_reference) RETVAL_FALSE; } else { object_init_ex(return_value, ldap_result_entry_ce); - resultentry = Z_LDAP_RESULT_ENTRY_P(return_value); + ldap_result_entry *resultentry = Z_LDAP_RESULT_ENTRY_P(return_value); ZVAL_COPY(&resultentry->res, result); resultentry->data = entry; resultentry->ber = NULL; @@ -3557,7 +3540,7 @@ PHP_FUNCTION(ldap_next_reference) { zval *link, *result_entry; ldap_linkdata *ld; - ldap_result_entry *resultentry, *resultentry_next; + ldap_result_entry *resultentry; LDAPMessage *entry_next; if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce) != SUCCESS) { @@ -3573,7 +3556,7 @@ PHP_FUNCTION(ldap_next_reference) RETVAL_FALSE; } else { object_init_ex(return_value, ldap_result_entry_ce); - resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value); + ldap_result_entry *resultentry_next = Z_LDAP_RESULT_ENTRY_P(return_value); ZVAL_COPY(&resultentry_next->res, &resultentry->res); resultentry_next->data = entry_next; resultentry_next->ber = NULL; @@ -3588,7 +3571,7 @@ PHP_FUNCTION(ldap_parse_reference) zval *link, *result_entry, *referrals; ldap_linkdata *ld; ldap_result_entry *resultentry; - char **lreferrals, **refp; + char **lreferrals; if (zend_parse_parameters(ZEND_NUM_ARGS(), "OOz", &link, ldap_link_ce, &result_entry, ldap_result_entry_ce, &referrals) != SUCCESS) { RETURN_THROWS(); @@ -3609,7 +3592,7 @@ PHP_FUNCTION(ldap_parse_reference) } if (lreferrals != NULL) { - refp = lreferrals; + char **refp = lreferrals; while (*refp) { add_next_index_string(referrals, *refp); refp++; @@ -3622,12 +3605,11 @@ PHP_FUNCTION(ldap_parse_reference) #endif /* {{{ php_ldap_do_rename */ -static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext) +static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, bool ext) { zval *link; ldap_linkdata *ld; LDAPControl **lserverctrls = NULL; - ldap_resultdata *result; LDAPMessage *ldap_res; int rc, msgid; char *dn, *newrdn, *newparent; @@ -3689,7 +3671,7 @@ static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext) /* return a PHP control object */ object_init_ex(return_value, ldap_result_ce); - result = Z_LDAP_RESULT_P(return_value); + ldap_resultdata *result = Z_LDAP_RESULT_P(return_value); result->result = ldap_res; } else { RETVAL_TRUE; @@ -3707,14 +3689,14 @@ static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext) /* {{{ Modify the name of an entry */ PHP_FUNCTION(ldap_rename) { - php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); } /* }}} */ /* {{{ Modify the name of an entry */ PHP_FUNCTION(ldap_rename_ext) { - php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } /* }}} */ @@ -3725,7 +3707,8 @@ PHP_FUNCTION(ldap_rename_ext) */ static int _php_ldap_tls_newctx(LDAP *ld) { - int val = 0, i, opts[] = { + int val = 0, i; + int str_opts[] = { #if (LDAP_API_VERSION > 2000) LDAP_OPT_X_TLS_CACERTDIR, LDAP_OPT_X_TLS_CACERTFILE, @@ -3745,21 +3728,42 @@ static int _php_ldap_tls_newctx(LDAP *ld) #endif 0}; - for (i=0 ; opts[i] ; i++) { + for (i=0 ; str_opts[i] ; i++) { char *path = NULL; - ldap_get_option(ld, opts[i], &path); + ldap_get_option(ld, str_opts[i], &path); if (path) { /* already set locally */ ldap_memfree(path); } else { - ldap_get_option(NULL, opts[i], &path); + ldap_get_option(NULL, str_opts[i], &path); if (path) { /* set globally, inherit */ - ldap_set_option(ld, opts[i], path); + ldap_set_option(ld, str_opts[i], path); ldap_memfree(path); } } } +#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN + int int_opts[] = { + LDAP_OPT_X_TLS_PROTOCOL_MIN, +#ifdef LDAP_OPT_X_TLS_PROTOCOL_MAX + LDAP_OPT_X_TLS_PROTOCOL_MAX, +#endif + 0 + }; + for (i=0 ; int_opts[i] ; i++) { + int value = 0; + + ldap_get_option(ld, int_opts[i], &value); + if (value <= 0) { /* if value is not set already */ + ldap_get_option(NULL, int_opts[i], &value); + if (value > 0) { /* set globally, inherit */ + ldap_set_option(ld, int_opts[i], &value); + } + } + } +#endif + return ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &val); } @@ -3795,7 +3799,7 @@ PHP_FUNCTION(ldap_start_tls) #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) /* {{{ _ldap_rebind_proc() */ -int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params) +static int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params) { ldap_linkdata *ld = NULL; int retval; @@ -3916,7 +3920,7 @@ static zend_string* php_ldap_do_escape(const bool *map, const char *value, size_ return ret; } -static void php_ldap_escape_map_set_chars(bool *map, const char *chars, const size_t charslen, char escape) +static void php_ldap_escape_map_set_chars(bool *map, const char *chars, const size_t charslen, bool escape) { size_t i = 0; while (i < charslen) { @@ -3928,7 +3932,6 @@ PHP_FUNCTION(ldap_escape) { char *value, *ignores; size_t valuelen = 0, ignoreslen = 0; - int i; zend_long flags = 0; bool map[256] = {0}, havecharlist = 0; @@ -3942,22 +3945,22 @@ PHP_FUNCTION(ldap_escape) if (flags & PHP_LDAP_ESCAPE_FILTER) { havecharlist = 1; - php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, 1); + php_ldap_escape_map_set_chars(map, "\\*()\0", sizeof("\\*()\0") - 1, true); } if (flags & PHP_LDAP_ESCAPE_DN) { havecharlist = 1; - php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#\r", sizeof("\\,=+<>;\"#\r") - 1, 1); + php_ldap_escape_map_set_chars(map, "\\,=+<>;\"#\r", sizeof("\\,=+<>;\"#\r") - 1, true); } if (!havecharlist) { - for (i = 0; i < 256; i++) { + for (uint16_t i = 0; i < 256; i++) { map[i] = 1; } } if (ignoreslen) { - php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0); + php_ldap_escape_map_set_chars(map, ignores, ignoreslen, false); } zend_string *result = php_ldap_do_escape(map, value, valuelen, flags); @@ -4212,7 +4215,7 @@ PHP_FUNCTION(ldap_exop_passwd) } if (serverctrls) { - _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0); + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, false); } /* return */ diff --git a/ext/ldap/tests/ldap_start_tls_rc_max_version.conf b/ext/ldap/tests/ldap_start_tls_rc_max_version.conf new file mode 100644 index 0000000000000..0cd03f8b8e191 --- /dev/null +++ b/ext/ldap/tests/ldap_start_tls_rc_max_version.conf @@ -0,0 +1 @@ +TLS_PROTOCOL_MAX 3.2 \ No newline at end of file diff --git a/ext/ldap/tests/ldap_start_tls_rc_max_version.phpt b/ext/ldap/tests/ldap_start_tls_rc_max_version.phpt new file mode 100644 index 0000000000000..e983b97c4b4ea --- /dev/null +++ b/ext/ldap/tests/ldap_start_tls_rc_max_version.phpt @@ -0,0 +1,45 @@ +--TEST-- +ldap_start_tls() - Basic ldap_start_tls test +--EXTENSIONS-- +ldap +--ENV-- +LDAPCONF={PWD}/ldap_start_tls_rc_max_version.conf +--SKIPIF-- + "OpenLDAP", + "min_version" => 20600, +]; +require_once __DIR__ .'/skipifbindfailure.inc'; +?> +--FILE-- + +--EXPECT-- +bool(false) +bool(false) +bool(false) diff --git a/ext/ldap/tests/skipifbindfailure.inc b/ext/ldap/tests/skipifbindfailure.inc index 1a0d0c6d1998b..81c7998cfbb59 100644 --- a/ext/ldap/tests/skipifbindfailure.inc +++ b/ext/ldap/tests/skipifbindfailure.inc @@ -10,4 +10,37 @@ if ($skip_on_bind_failure) { ldap_unbind($link); } + +if (isset($require_vendor)) { + ob_start(); + phpinfo(INFO_MODULES); + $phpinfo = ob_get_clean(); + + // Extract the LDAP section specifically + if (preg_match('/^ldap\s*$(.*?)^[a-z_]+\s*$/ims', $phpinfo, $ldap_section_match)) { + $ldap_section = $ldap_section_match[1]; + + // Extract vendor info from the LDAP section only + if (preg_match('/Vendor Name\s*=>\s*(.+)/i', $ldap_section, $name_match) && + preg_match('/Vendor Version\s*=>\s*(\d+)/i', $ldap_section, $version_match)) { + + $vendor_name = trim($name_match[1]); + $vendor_version = (int)$version_match[1]; + + // Check vendor name if specified + if (isset($require_vendor['name']) && $vendor_name !== $require_vendor['name']) { + die("skip Requires {$require_vendor['name']} (detected: $vendor_name)"); + } + + // Check minimum version if specified + if (isset($require_vendor['min_version']) && $vendor_version < $require_vendor['min_version']) { + die("skip Requires minimum version {$require_vendor['min_version']} (detected: $vendor_version)"); + } + } else { + die("skip Cannot determine LDAP vendor information"); + } + } else { + die("skip LDAP extension information not found"); + } +} ?> diff --git a/ext/lexbor/lexbor/core/base.h b/ext/lexbor/lexbor/core/base.h index 3c14dcff4cc3e..d3a04880f2206 100644 --- a/ext/lexbor/lexbor/core/base.h +++ b/ext/lexbor/lexbor/core/base.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2024 Alexander Borisov + * Copyright (C) 2018-2025 Alexander Borisov * * Author: Alexander Borisov */ @@ -26,8 +26,8 @@ extern "C" { #include "lexbor/core/types.h" #include "lexbor/core/lexbor.h" -#define LEXBOR_VERSION_MAJOR 1 -#define LEXBOR_VERSION_MINOR 8 +#define LEXBOR_VERSION_MAJOR 2 +#define LEXBOR_VERSION_MINOR 0 #define LEXBOR_VERSION_PATCH 0 #define LEXBOR_VERSION_STRING LEXBOR_STRINGIZE(LEXBOR_VERSION_MAJOR) "." \ diff --git a/ext/lexbor/lexbor/core/dobject.h b/ext/lexbor/lexbor/core/dobject.h index c92930cfa9326..69497fd40ec0d 100644 --- a/ext/lexbor/lexbor/core/dobject.h +++ b/ext/lexbor/lexbor/core/dobject.h @@ -40,10 +40,6 @@ LXB_API lexbor_dobject_t * lexbor_dobject_destroy(lexbor_dobject_t *dobject, bool destroy_self); -LXB_API uint8_t * -lexbor_dobject_init_list_entries(lexbor_dobject_t *dobject, size_t pos); - - LXB_API void * lexbor_dobject_alloc(lexbor_dobject_t *dobject); diff --git a/ext/lexbor/lexbor/core/in.c b/ext/lexbor/lexbor/core/in.c index 9214e198950d8..951e585cbd399 100644 --- a/ext/lexbor/lexbor/core/in.c +++ b/ext/lexbor/lexbor/core/in.c @@ -65,7 +65,7 @@ lexbor_in_node_make(lexbor_in_t *incoming, lexbor_in_node_t *last_node, node->opt = LEXBOR_IN_OPT_UNDEF; node->begin = buf; - node->end = buf + buf_size; + node->end = buf ? (buf + buf_size) : NULL; node->use = buf; if (last_node != NULL) { diff --git a/ext/lexbor/lexbor/core/str.c b/ext/lexbor/lexbor/core/str.c index 0f04286bdea56..d11a08614dd42 100644 --- a/ext/lexbor/lexbor/core/str.c +++ b/ext/lexbor/lexbor/core/str.c @@ -133,6 +133,10 @@ lexbor_str_append(lexbor_str_t *str, lexbor_mraw_t *mraw, { lxb_char_t *data_begin; + if (length == 0) { + return str->data; + } + lexbor_str_check_size_arg_m(str, lexbor_str_size(str), mraw, (length + 1), NULL); diff --git a/ext/lexbor/lexbor/dom/interfaces/document_type.h b/ext/lexbor/lexbor/dom/interfaces/document_type.h index 0e0d35d5e188e..366aaba409ac1 100644 --- a/ext/lexbor/lexbor/dom/interfaces/document_type.h +++ b/ext/lexbor/lexbor/dom/interfaces/document_type.h @@ -16,7 +16,6 @@ extern "C" { #include "lexbor/dom/interfaces/document.h" #include "lexbor/dom/interfaces/node.h" #include "lexbor/dom/interfaces/attr.h" -#include "lexbor/dom/interfaces/document_type.h" struct lxb_dom_document_type { diff --git a/ext/lexbor/lexbor/dom/interfaces/node.c b/ext/lexbor/lexbor/dom/interfaces/node.c index ade06fca17990..a588ed388e483 100644 --- a/ext/lexbor/lexbor/dom/interfaces/node.c +++ b/ext/lexbor/lexbor/dom/interfaces/node.c @@ -248,11 +248,6 @@ lxb_dom_node_t * lxb_dom_node_destroy(lxb_dom_node_t *node) { lxb_dom_node_remove(node); - - if (node->owner_document->node_cb->destroy != NULL) { - node->owner_document->node_cb->destroy(node); - } - return lxb_dom_document_destroy_interface(node); } diff --git a/ext/lexbor/lexbor/html/interface_res.h b/ext/lexbor/lexbor/html/interface_res.h index 08667af19ba8e..980be3c7de014 100644 --- a/ext/lexbor/lexbor/html/interface_res.h +++ b/ext/lexbor/lexbor/html/interface_res.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Alexander Borisov + * Copyright (C) 2018-2025 Alexander Borisov * * Author: Alexander Borisov */ @@ -118,6 +118,907 @@ #include "lexbor/html/interfaces/video_element.h" #include "lexbor/html/interfaces/window.h" +lxb_inline void * +lxb_dom_element_interface_create_wrapper(void *interface) +{ + return lxb_dom_element_interface_create(interface); +} + +lxb_inline void * +lxb_dom_element_interface_destroy_wrapper(void *interface) +{ + return lxb_dom_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_unknown_element_interface_create_wrapper(void *interface) +{ + return lxb_html_unknown_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_unknown_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_unknown_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_element_interface_create_wrapper(void *interface) +{ + return lxb_html_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_dom_text_interface_create_wrapper(void *interface) +{ + return lxb_dom_text_interface_create(interface); +} + +lxb_inline void * +lxb_dom_text_interface_destroy_wrapper(void *interface) +{ + return lxb_dom_text_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_document_interface_create_wrapper(void *interface) +{ + return lxb_html_document_interface_create(interface); +} + +lxb_inline void * +lxb_html_document_interface_destroy_wrapper(void *interface) +{ + return lxb_html_document_interface_destroy(interface); +} + +lxb_inline void * +lxb_dom_comment_interface_create_wrapper(void *interface) +{ + return lxb_dom_comment_interface_create(interface); +} + +lxb_inline void * +lxb_dom_comment_interface_destroy_wrapper(void *interface) +{ + return lxb_dom_comment_interface_destroy(interface); +} + +lxb_inline void * +lxb_dom_document_type_interface_create_wrapper(void *interface) +{ + return lxb_dom_document_type_interface_create(interface); +} + +lxb_inline void * +lxb_dom_document_type_interface_destroy_wrapper(void *interface) +{ + return lxb_dom_document_type_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_anchor_element_interface_create_wrapper(void *interface) +{ + return lxb_html_anchor_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_anchor_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_anchor_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_area_element_interface_create_wrapper(void *interface) +{ + return lxb_html_area_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_area_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_area_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_audio_element_interface_create_wrapper(void *interface) +{ + return lxb_html_audio_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_audio_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_audio_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_base_element_interface_create_wrapper(void *interface) +{ + return lxb_html_base_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_base_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_base_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_quote_element_interface_create_wrapper(void *interface) +{ + return lxb_html_quote_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_quote_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_quote_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_body_element_interface_create_wrapper(void *interface) +{ + return lxb_html_body_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_body_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_body_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_br_element_interface_create_wrapper(void *interface) +{ + return lxb_html_br_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_br_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_br_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_button_element_interface_create_wrapper(void *interface) +{ + return lxb_html_button_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_button_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_button_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_canvas_element_interface_create_wrapper(void *interface) +{ + return lxb_html_canvas_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_canvas_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_canvas_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_table_caption_element_interface_create_wrapper(void *interface) +{ + return lxb_html_table_caption_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_table_caption_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_table_caption_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_table_col_element_interface_create_wrapper(void *interface) +{ + return lxb_html_table_col_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_table_col_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_table_col_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_data_element_interface_create_wrapper(void *interface) +{ + return lxb_html_data_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_data_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_data_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_data_list_element_interface_create_wrapper(void *interface) +{ + return lxb_html_data_list_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_data_list_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_data_list_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_mod_element_interface_create_wrapper(void *interface) +{ + return lxb_html_mod_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_mod_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_mod_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_details_element_interface_create_wrapper(void *interface) +{ + return lxb_html_details_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_details_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_details_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_dialog_element_interface_create_wrapper(void *interface) +{ + return lxb_html_dialog_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_dialog_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_dialog_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_directory_element_interface_create_wrapper(void *interface) +{ + return lxb_html_directory_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_directory_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_directory_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_div_element_interface_create_wrapper(void *interface) +{ + return lxb_html_div_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_div_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_div_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_d_list_element_interface_create_wrapper(void *interface) +{ + return lxb_html_d_list_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_d_list_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_d_list_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_embed_element_interface_create_wrapper(void *interface) +{ + return lxb_html_embed_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_embed_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_embed_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_field_set_element_interface_create_wrapper(void *interface) +{ + return lxb_html_field_set_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_field_set_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_field_set_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_font_element_interface_create_wrapper(void *interface) +{ + return lxb_html_font_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_font_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_font_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_form_element_interface_create_wrapper(void *interface) +{ + return lxb_html_form_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_form_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_form_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_frame_element_interface_create_wrapper(void *interface) +{ + return lxb_html_frame_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_frame_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_frame_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_frame_set_element_interface_create_wrapper(void *interface) +{ + return lxb_html_frame_set_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_frame_set_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_frame_set_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_heading_element_interface_create_wrapper(void *interface) +{ + return lxb_html_heading_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_heading_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_heading_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_head_element_interface_create_wrapper(void *interface) +{ + return lxb_html_head_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_head_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_head_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_hr_element_interface_create_wrapper(void *interface) +{ + return lxb_html_hr_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_hr_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_hr_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_html_element_interface_create_wrapper(void *interface) +{ + return lxb_html_html_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_html_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_html_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_iframe_element_interface_create_wrapper(void *interface) +{ + return lxb_html_iframe_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_iframe_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_iframe_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_image_element_interface_create_wrapper(void *interface) +{ + return lxb_html_image_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_image_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_image_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_input_element_interface_create_wrapper(void *interface) +{ + return lxb_html_input_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_input_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_input_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_label_element_interface_create_wrapper(void *interface) +{ + return lxb_html_label_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_label_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_label_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_legend_element_interface_create_wrapper(void *interface) +{ + return lxb_html_legend_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_legend_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_legend_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_li_element_interface_create_wrapper(void *interface) +{ + return lxb_html_li_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_li_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_li_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_link_element_interface_create_wrapper(void *interface) +{ + return lxb_html_link_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_link_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_link_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_pre_element_interface_create_wrapper(void *interface) +{ + return lxb_html_pre_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_pre_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_pre_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_map_element_interface_create_wrapper(void *interface) +{ + return lxb_html_map_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_map_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_map_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_marquee_element_interface_create_wrapper(void *interface) +{ + return lxb_html_marquee_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_marquee_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_marquee_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_menu_element_interface_create_wrapper(void *interface) +{ + return lxb_html_menu_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_menu_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_menu_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_meta_element_interface_create_wrapper(void *interface) +{ + return lxb_html_meta_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_meta_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_meta_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_meter_element_interface_create_wrapper(void *interface) +{ + return lxb_html_meter_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_meter_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_meter_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_object_element_interface_create_wrapper(void *interface) +{ + return lxb_html_object_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_object_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_object_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_o_list_element_interface_create_wrapper(void *interface) +{ + return lxb_html_o_list_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_o_list_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_o_list_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_opt_group_element_interface_create_wrapper(void *interface) +{ + return lxb_html_opt_group_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_opt_group_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_opt_group_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_option_element_interface_create_wrapper(void *interface) +{ + return lxb_html_option_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_option_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_option_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_output_element_interface_create_wrapper(void *interface) +{ + return lxb_html_output_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_output_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_output_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_paragraph_element_interface_create_wrapper(void *interface) +{ + return lxb_html_paragraph_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_paragraph_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_paragraph_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_param_element_interface_create_wrapper(void *interface) +{ + return lxb_html_param_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_param_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_param_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_picture_element_interface_create_wrapper(void *interface) +{ + return lxb_html_picture_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_picture_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_picture_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_progress_element_interface_create_wrapper(void *interface) +{ + return lxb_html_progress_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_progress_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_progress_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_script_element_interface_create_wrapper(void *interface) +{ + return lxb_html_script_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_script_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_script_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_select_element_interface_create_wrapper(void *interface) +{ + return lxb_html_select_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_select_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_select_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_slot_element_interface_create_wrapper(void *interface) +{ + return lxb_html_slot_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_slot_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_slot_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_source_element_interface_create_wrapper(void *interface) +{ + return lxb_html_source_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_source_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_source_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_span_element_interface_create_wrapper(void *interface) +{ + return lxb_html_span_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_span_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_span_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_style_element_interface_create_wrapper(void *interface) +{ + return lxb_html_style_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_style_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_style_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_table_element_interface_create_wrapper(void *interface) +{ + return lxb_html_table_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_table_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_table_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_table_section_element_interface_create_wrapper(void *interface) +{ + return lxb_html_table_section_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_table_section_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_table_section_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_table_cell_element_interface_create_wrapper(void *interface) +{ + return lxb_html_table_cell_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_table_cell_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_table_cell_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_template_element_interface_create_wrapper(void *interface) +{ + return lxb_html_template_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_template_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_template_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_text_area_element_interface_create_wrapper(void *interface) +{ + return lxb_html_text_area_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_text_area_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_text_area_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_time_element_interface_create_wrapper(void *interface) +{ + return lxb_html_time_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_time_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_time_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_title_element_interface_create_wrapper(void *interface) +{ + return lxb_html_title_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_title_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_title_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_table_row_element_interface_create_wrapper(void *interface) +{ + return lxb_html_table_row_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_table_row_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_table_row_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_track_element_interface_create_wrapper(void *interface) +{ + return lxb_html_track_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_track_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_track_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_u_list_element_interface_create_wrapper(void *interface) +{ + return lxb_html_u_list_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_u_list_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_u_list_element_interface_destroy(interface); +} + +lxb_inline void * +lxb_html_video_element_interface_create_wrapper(void *interface) +{ + return lxb_html_video_element_interface_create(interface); +} + +lxb_inline void * +lxb_html_video_element_interface_destroy_wrapper(void *interface) +{ + return lxb_html_video_element_interface_destroy(interface); +} + + #ifdef LXB_HTML_INTERFACE_RES_CONSTRUCTORS #ifndef LXB_HTML_INTERFACE_RES_CONSTRUCTORS_ENABLED #define LXB_HTML_INTERFACE_RES_CONSTRUCTORS_ENABLED @@ -125,2159 +1026,2159 @@ static lxb_dom_interface_constructor_f lxb_html_interface_res_constructors[LXB_ { /* LXB_TAG__UNDEF */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG__END_OF_FILE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG__TEXT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_text_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG__DOCUMENT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_document_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_document_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG__EM_COMMENT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_comment_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG__EM_DOCTYPE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_document_type_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_A */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_anchor_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_anchor_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ABBR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ACRONYM */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ADDRESS */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ALTGLYPH */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ALTGLYPHDEF */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ALTGLYPHITEM */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ANIMATECOLOR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ANIMATEMOTION */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ANIMATETRANSFORM */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ANNOTATION_XML */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_APPLET */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_AREA */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_area_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_area_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ARTICLE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ASIDE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_AUDIO */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_audio_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_audio_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_B */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BASE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_base_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_base_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BASEFONT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BDI */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BDO */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BGSOUND */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BIG */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BLINK */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BLOCKQUOTE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_quote_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_quote_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BODY */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_body_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_body_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_br_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_br_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_BUTTON */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_button_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_button_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_CANVAS */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_canvas_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_canvas_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_CAPTION */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_caption_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_caption_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_CENTER */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_CITE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_CLIPPATH */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_CODE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_COL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_col_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_col_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_COLGROUP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_col_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_col_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DATA */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_data_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_data_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DATALIST */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_data_list_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_data_list_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DD */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DEL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_mod_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_mod_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DESC */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DETAILS */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_details_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_details_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DFN */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DIALOG */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_dialog_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_dialog_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DIR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_directory_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_directory_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DIV */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_div_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_div_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_d_list_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_d_list_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_DT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_EM */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_EMBED */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_embed_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_embed_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEBLEND */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FECOLORMATRIX */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FECOMPONENTTRANSFER */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FECOMPOSITE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FECONVOLVEMATRIX */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEDIFFUSELIGHTING */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEDISPLACEMENTMAP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEDISTANTLIGHT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEDROPSHADOW */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEFLOOD */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEFUNCA */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEFUNCB */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEFUNCG */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEFUNCR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEGAUSSIANBLUR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEIMAGE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEMERGE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEMERGENODE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEMORPHOLOGY */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEOFFSET */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FEPOINTLIGHT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FESPECULARLIGHTING */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FESPOTLIGHT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FETILE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FETURBULENCE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FIELDSET */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_field_set_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_field_set_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FIGCAPTION */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FIGURE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FONT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_font_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_font_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FOOTER */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FOREIGNOBJECT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FORM */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_form_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_form_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FRAME */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_frame_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_frame_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_FRAMESET */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_frame_set_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_frame_set_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_GLYPHREF */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_H1 */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_H2 */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_H3 */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_H4 */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_H5 */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_H6 */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_heading_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_HEAD */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_head_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_head_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_HEADER */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_HGROUP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_HR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_hr_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_hr_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_HTML */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_I */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_IFRAME */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_iframe_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_iframe_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_IMAGE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_image_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_image_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_IMG */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_image_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_image_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_INPUT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_input_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_input_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_INS */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_mod_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_mod_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_ISINDEX */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_KBD */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_KEYGEN */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_LABEL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_label_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_label_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_LEGEND */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_legend_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_legend_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_LI */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_li_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_li_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_LINEARGRADIENT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_LINK */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_link_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_link_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_LISTING */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MAIN */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MALIGNMARK */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MAP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_map_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_map_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MARK */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MARQUEE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_marquee_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_marquee_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MATH */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MENU */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_menu_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_menu_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_META */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_meta_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_meta_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_METER */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_meter_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_meter_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MFENCED */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MGLYPH */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MI */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MN */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MO */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MS */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MTEXT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_MULTICOL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_NAV */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_NEXTID */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_NOBR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_NOEMBED */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_NOFRAMES */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_NOSCRIPT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_OBJECT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_object_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_object_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_OL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_o_list_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_o_list_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_OPTGROUP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_opt_group_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_opt_group_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_OPTION */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_option_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_option_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_OUTPUT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_output_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_output_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_P */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_paragraph_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_paragraph_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_PARAM */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_param_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_param_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_PATH */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_PICTURE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_picture_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_picture_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_PLAINTEXT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_PRE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_PROGRESS */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_progress_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_progress_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_Q */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_quote_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_quote_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_RADIALGRADIENT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_RB */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_RP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_RT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_RTC */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_RUBY */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_S */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SAMP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SCRIPT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_script_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_script_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SECTION */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SELECT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_select_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_select_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SLOT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_slot_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_slot_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SMALL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SOURCE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_source_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_source_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SPACER */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SPAN */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_span_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_span_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_STRIKE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_STRONG */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_STYLE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_style_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_style_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SUB */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SUMMARY */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SUP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_SVG */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TABLE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TBODY */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TD */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_cell_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_cell_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TEMPLATE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_template_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_template_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TEXTAREA */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_text_area_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_text_area_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TEXTPATH */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TFOOT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TH */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_cell_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_cell_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_THEAD */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_section_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TIME */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_time_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_time_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TITLE */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_title_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_title_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_table_row_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_table_row_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TRACK */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_track_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_track_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_TT */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_U */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_UL */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_u_list_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_u_list_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_VAR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_VIDEO */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_video_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_video_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_WBR */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper }, /* LXB_TAG_XMP */ { - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create, - (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_unknown_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_html_pre_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper, + (lxb_dom_interface_constructor_f) lxb_dom_element_interface_create_wrapper } }; #endif /* LXB_HTML_INTERFACE_RES_CONSTRUCTORS_ENABLED */ @@ -2290,2159 +3191,2159 @@ static lxb_dom_interface_destructor_f lxb_html_interface_res_destructor[LXB_TAG { /* LXB_TAG__UNDEF */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG__END_OF_FILE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG__TEXT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_text_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG__DOCUMENT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_document_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_document_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG__EM_COMMENT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_comment_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG__EM_DOCTYPE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_document_type_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_A */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_anchor_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_anchor_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ABBR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ACRONYM */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ADDRESS */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ALTGLYPH */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ALTGLYPHDEF */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ALTGLYPHITEM */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ANIMATECOLOR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ANIMATEMOTION */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ANIMATETRANSFORM */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ANNOTATION_XML */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_APPLET */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_AREA */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_area_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_area_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ARTICLE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ASIDE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_AUDIO */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_audio_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_audio_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_B */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BASE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_base_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_base_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BASEFONT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BDI */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BDO */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BGSOUND */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BIG */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BLINK */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BLOCKQUOTE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_quote_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_quote_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BODY */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_body_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_body_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_br_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_br_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_BUTTON */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_button_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_button_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_CANVAS */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_canvas_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_canvas_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_CAPTION */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_caption_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_caption_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_CENTER */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_CITE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_CLIPPATH */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_CODE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_COL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_col_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_col_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_COLGROUP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_col_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_col_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DATA */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_data_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_data_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DATALIST */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_data_list_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_data_list_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DD */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DEL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_mod_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_mod_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DESC */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DETAILS */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_details_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_details_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DFN */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DIALOG */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_dialog_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_dialog_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DIR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_directory_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_directory_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DIV */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_div_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_div_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_d_list_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_d_list_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_DT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_EM */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_EMBED */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_embed_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_embed_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEBLEND */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FECOLORMATRIX */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FECOMPONENTTRANSFER */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FECOMPOSITE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FECONVOLVEMATRIX */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEDIFFUSELIGHTING */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEDISPLACEMENTMAP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEDISTANTLIGHT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEDROPSHADOW */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEFLOOD */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEFUNCA */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEFUNCB */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEFUNCG */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEFUNCR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEGAUSSIANBLUR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEIMAGE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEMERGE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEMERGENODE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEMORPHOLOGY */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEOFFSET */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FEPOINTLIGHT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FESPECULARLIGHTING */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FESPOTLIGHT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FETILE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FETURBULENCE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FIELDSET */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_field_set_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_field_set_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FIGCAPTION */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FIGURE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FONT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_font_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_font_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FOOTER */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FOREIGNOBJECT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FORM */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_form_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_form_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FRAME */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_frame_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_frame_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_FRAMESET */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_frame_set_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_frame_set_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_GLYPHREF */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_H1 */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_H2 */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_H3 */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_H4 */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_H5 */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_H6 */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_heading_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_HEAD */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_head_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_head_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_HEADER */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_HGROUP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_HR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_hr_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_hr_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_HTML */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_I */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_IFRAME */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_iframe_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_iframe_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_IMAGE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_image_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_image_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_IMG */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_image_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_image_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_INPUT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_input_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_input_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_INS */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_mod_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_mod_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_ISINDEX */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_KBD */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_KEYGEN */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_LABEL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_label_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_label_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_LEGEND */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_legend_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_legend_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_LI */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_li_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_li_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_LINEARGRADIENT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_LINK */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_link_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_link_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_LISTING */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MAIN */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MALIGNMARK */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MAP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_map_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_map_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MARK */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MARQUEE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_marquee_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_marquee_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MATH */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MENU */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_menu_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_menu_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_META */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_meta_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_meta_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_METER */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_meter_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_meter_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MFENCED */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MGLYPH */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MI */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MN */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MO */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MS */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MTEXT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_MULTICOL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_NAV */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_NEXTID */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_NOBR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_NOEMBED */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_NOFRAMES */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_NOSCRIPT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_OBJECT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_object_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_object_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_OL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_o_list_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_o_list_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_OPTGROUP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_opt_group_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_opt_group_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_OPTION */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_option_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_option_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_OUTPUT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_output_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_output_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_P */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_paragraph_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_paragraph_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_PARAM */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_param_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_param_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_PATH */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_PICTURE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_picture_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_picture_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_PLAINTEXT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_PRE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_PROGRESS */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_progress_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_progress_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_Q */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_quote_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_quote_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_RADIALGRADIENT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_RB */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_RP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_RT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_RTC */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_RUBY */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_S */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SAMP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SCRIPT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_script_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_script_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SECTION */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SELECT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_select_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_select_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SLOT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_slot_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_slot_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SMALL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SOURCE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_source_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_source_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SPACER */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SPAN */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_span_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_span_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_STRIKE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_STRONG */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_STYLE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_style_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_style_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SUB */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SUMMARY */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SUP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_SVG */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TABLE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TBODY */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TD */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_cell_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_cell_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TEMPLATE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_template_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_template_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TEXTAREA */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_text_area_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_text_area_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TEXTPATH */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TFOOT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TH */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_cell_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_cell_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_THEAD */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_section_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TIME */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_time_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_time_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TITLE */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_title_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_title_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_table_row_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_table_row_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TRACK */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_track_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_track_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_TT */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_U */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_UL */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_u_list_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_u_list_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_VAR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_VIDEO */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_video_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_video_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_WBR */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper }, /* LXB_TAG_XMP */ { - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy, - (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_unknown_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_html_pre_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper, + (lxb_dom_interface_destructor_f) lxb_dom_element_interface_destroy_wrapper } }; #endif /* LXB_HTML_INTERFACE_RES_DESTRUCTOR_ENABLED */ diff --git a/ext/lexbor/lexbor/html/interfaces/document.c b/ext/lexbor/lexbor/html/interfaces/document.c index 48f8403a9e913..34a2c6db0e5a0 100644 --- a/ext/lexbor/lexbor/html/interfaces/document.c +++ b/ext/lexbor/lexbor/html/interfaces/document.c @@ -33,12 +33,19 @@ static lexbor_action_t lxb_html_document_title_walker(lxb_dom_node_t *node, void *ctx); +lxb_inline lxb_dom_interface_t * +lxb_html_document_interface_create_wrapper(lxb_dom_document_t *document, + lxb_tag_id_t tag_id, lxb_ns_id_t ns) +{ + return lxb_html_interface_create(lxb_html_interface_document(document), + tag_id, ns); +} + lxb_html_document_t * lxb_html_document_interface_create(lxb_html_document_t *document) { lxb_status_t status; lxb_dom_document_t *doc; - lxb_dom_interface_create_f icreator; if (document != NULL) { doc = lexbor_mraw_calloc(lxb_html_document_mraw(document), @@ -52,10 +59,9 @@ lxb_html_document_interface_create(lxb_html_document_t *document) return NULL; } - icreator = (lxb_dom_interface_create_f) lxb_html_interface_create; - status = lxb_dom_document_init(doc, lxb_dom_interface_document(document), - icreator, lxb_html_interface_clone, + lxb_html_document_interface_create_wrapper, + lxb_html_interface_clone, lxb_html_interface_destroy, LXB_DOM_DOCUMENT_DTYPE_HTML, LXB_NS_HTML); if (status != LXB_STATUS_OK) { diff --git a/ext/lexbor/lexbor/selectors/selectors.c b/ext/lexbor/lexbor/selectors/selectors.c deleted file mode 100644 index 8ad7fc0730c91..0000000000000 --- a/ext/lexbor/lexbor/selectors/selectors.c +++ /dev/null @@ -1,1925 +0,0 @@ -/* - * Copyright (C) 2021-2024 Alexander Borisov - * - * Author: Alexander Borisov - */ - -#include "lexbor/selectors/selectors.h" - -#include - - -static lxb_status_t -lxb_selectors_state_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root, - const lxb_css_selector_list_t *list); - -static lxb_status_t -lxb_selectors_state_run(lxb_selectors_t *selectors, lxb_dom_node_t *node, - const lxb_css_selector_list_t *list); - -static lxb_selectors_entry_t * -lxb_selectors_state_find(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); - -static lxb_selectors_entry_t * -lxb_selectors_state_find_check(lxb_selectors_t *selectors, lxb_dom_node_t *node, - const lxb_css_selector_t *selector, - lxb_selectors_entry_t *entry); - -static lxb_selectors_entry_t * -lxb_selectors_state_pseudo_class_function(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); - -static lxb_dom_node_t * -lxb_selectors_next_node(lxb_selectors_nested_t *main); - -static lxb_dom_node_t * -lxb_selectors_state_has_relative(lxb_dom_node_t *node, - const lxb_css_selector_t *selector); - -static lxb_selectors_entry_t * -lxb_selectors_state_after_find_has(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); - -static lxb_selectors_entry_t * -lxb_selectors_state_after_find(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); - -static lxb_selectors_entry_t * -lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); - -static bool -lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, lxb_dom_node_t *node); - -static bool -lxb_selectors_match_element(const lxb_css_selector_t *selector, - lxb_dom_node_t *node, lxb_selectors_entry_t *entry); - -static bool -lxb_selectors_match_id(const lxb_css_selector_t *selector, lxb_dom_node_t *node); - -static bool -lxb_selectors_match_class(const lexbor_str_t *target, const lexbor_str_t *src, - bool quirks); - -static bool -lxb_selectors_match_attribute(const lxb_css_selector_t *selector, - lxb_dom_node_t *node, lxb_selectors_entry_t *entry); - -static bool -lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, - const lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, - lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_element(const lxb_css_selector_t *selector, - const lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_class_disabled(const lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_class_first_child(const lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_class_first_of_type(const lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_class_last_child(const lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_class_last_of_type(const lxb_dom_node_t *node); - -static bool -lxb_selectors_pseudo_class_read_write(const lxb_dom_node_t *node); - -static bool -lxb_selectors_anb_calc(lxb_css_selector_anb_of_t *anb, size_t index); - -static lxb_status_t -lxb_selectors_cb_ok(lxb_dom_node_t *node, - lxb_css_selector_specificity_t spec, void *ctx); - -static lxb_status_t -lxb_selectors_cb_not(lxb_dom_node_t *node, - lxb_css_selector_specificity_t spec, void *ctx); - - -lxb_selectors_t * -lxb_selectors_create(void) -{ - return lexbor_calloc(1, sizeof(lxb_selectors_t)); -} - -lxb_status_t -lxb_selectors_init(lxb_selectors_t *selectors) -{ - lxb_status_t status; - - if (selectors == NULL) { - return LXB_STATUS_ERROR_INCOMPLETE_OBJECT; - } - - selectors->objs = lexbor_dobject_create(); - status = lexbor_dobject_init(selectors->objs, - 128, sizeof(lxb_selectors_entry_t)); - if (status != LXB_STATUS_OK) { - return status; - } - - selectors->nested = lexbor_dobject_create(); - status = lexbor_dobject_init(selectors->nested, - 64, sizeof(lxb_selectors_nested_t)); - if (status != LXB_STATUS_OK) { - return status; - } - - selectors->options = LXB_SELECTORS_OPT_DEFAULT; - - return LXB_STATUS_OK; -} - -void -lxb_selectors_clean(lxb_selectors_t *selectors) -{ - lexbor_dobject_clean(selectors->objs); - lexbor_dobject_clean(selectors->nested); -} - -lxb_selectors_t * -lxb_selectors_destroy(lxb_selectors_t *selectors, bool self_destroy) -{ - if (selectors == NULL) { - return NULL; - } - - selectors->objs = lexbor_dobject_destroy(selectors->objs, true); - selectors->nested = lexbor_dobject_destroy(selectors->nested, true); - - if (self_destroy) { - return lexbor_free(selectors); - } - - return selectors; -} - -lxb_inline lxb_dom_node_t * -lxb_selectors_descendant(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, - lxb_dom_node_t *node) -{ - node = node->parent; - - while (node != NULL) { - if (node->type == LXB_DOM_NODE_TYPE_ELEMENT - && lxb_selectors_match(selectors, entry, selector, node)) - { - return node; - } - - node = node->parent; - } - - return NULL; -} - -lxb_inline lxb_dom_node_t * -lxb_selectors_close(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, lxb_dom_node_t *node) -{ - if (lxb_selectors_match(selectors, entry, selector, node)) { - return node; - } - - return NULL; -} - -lxb_inline lxb_dom_node_t * -lxb_selectors_child(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, lxb_dom_node_t *root) -{ - root = root->parent; - - if (root != NULL && root->type == LXB_DOM_NODE_TYPE_ELEMENT - && lxb_selectors_match(selectors, entry, selector, root)) - { - return root; - } - - return NULL; -} - -lxb_inline lxb_dom_node_t * -lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, lxb_dom_node_t *node) -{ - node = node->prev; - - while (node != NULL) { - if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) { - if (lxb_selectors_match(selectors, entry, selector, node)) { - return node; - } - - return NULL; - } - - node = node->prev; - } - - return NULL; -} - -lxb_inline lxb_dom_node_t * -lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, lxb_dom_node_t *node) -{ - node = node->prev; - - while (node != NULL) { - if (node->type == LXB_DOM_NODE_TYPE_ELEMENT && - lxb_selectors_match(selectors, entry, selector, node)) - { - return node; - } - - node = node->prev; - } - - return NULL; -} - -lxb_status_t -lxb_selectors_find(lxb_selectors_t *selectors, lxb_dom_node_t *root, - const lxb_css_selector_list_t *list, - lxb_selectors_cb_f cb, void *ctx) -{ - lxb_selectors_entry_t *entry; - lxb_selectors_nested_t nested; - - entry = lexbor_dobject_calloc(selectors->objs); - if (entry == NULL) { - return LXB_STATUS_ERROR_MEMORY_ALLOCATION; - } - - entry->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - entry->selector = list->last; - - nested.parent = NULL; - nested.entry = entry; - nested.cb = cb; - nested.ctx = ctx; - - selectors->current = &nested; - selectors->status = LXB_STATUS_OK; - - return lxb_selectors_state_tree(selectors, root, list); -} - -lxb_status_t -lxb_selectors_match_node(lxb_selectors_t *selectors, lxb_dom_node_t *node, - const lxb_css_selector_list_t *list, - lxb_selectors_cb_f cb, void *ctx) -{ - lxb_status_t status; - lxb_selectors_entry_t *entry; - lxb_selectors_nested_t nested; - - if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) { - return LXB_STATUS_OK; - } - - entry = lexbor_dobject_calloc(selectors->objs); - if (entry == NULL) { - return LXB_STATUS_ERROR_MEMORY_ALLOCATION; - } - - entry->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - entry->selector = list->last; - - nested.parent = NULL; - nested.entry = entry; - nested.cb = cb; - nested.ctx = ctx; - - selectors->current = &nested; - selectors->status = LXB_STATUS_OK; - - status = lxb_selectors_state_run(selectors, node, list); - - lxb_selectors_clean(selectors); - - return status; -} - -lxb_status_t -lxb_selectors_find_reverse(lxb_selectors_t *selectors, lxb_dom_node_t *root, - lxb_css_selector_list_t *list, - lxb_selectors_cb_f cb, void *ctx) -{ - return lxb_selectors_find(selectors, root, list, cb, ctx); -} - -static lxb_status_t -lxb_selectors_state_tree(lxb_selectors_t *selectors, lxb_dom_node_t *root, - const lxb_css_selector_list_t *list) -{ - lxb_status_t status; - lxb_dom_node_t *node; - - if (selectors->options & LXB_SELECTORS_OPT_MATCH_ROOT) { - node = root; - - if (node->type == LXB_DOM_NODE_TYPE_DOCUMENT) { - node = root->first_child; - } - } - else { - node = root->first_child; - } - - if (node == NULL) { - goto out; - } - - do { - if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) { - goto next; - } - - status = lxb_selectors_state_run(selectors, node, list); - if (status != LXB_STATUS_OK) { - if (status == LXB_STATUS_STOP) { - break; - } - - lxb_selectors_clean(selectors); - - return status; - } - - if (node->first_child != NULL) { - node = node->first_child; - } - else { - - next: - - while (node != root && node->next == NULL) { - node = node->parent; - } - - if (node == root) { - break; - } - - node = node->next; - } - } - while (true); - -out: - lxb_selectors_clean(selectors); - - return LXB_STATUS_OK; -} - -static lxb_status_t -lxb_selectors_state_run(lxb_selectors_t *selectors, lxb_dom_node_t *node, - const lxb_css_selector_list_t *list) -{ - lxb_selectors_entry_t *entry; - - entry = selectors->current->entry; - - entry->node = node; - selectors->state = lxb_selectors_state_find; - selectors->first = entry; - -again: - - do { - entry = selectors->state(selectors, entry); - } - while (entry != NULL); - - if (selectors->current->parent != NULL - && selectors->status == LXB_STATUS_OK) - { - entry = selectors->current->entry; - selectors->state = selectors->current->return_state; - - goto again; - } - - return selectors->status; -} - -static lxb_selectors_entry_t * -lxb_selectors_state_find(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) -{ - lxb_dom_node_t *node; - lxb_selectors_entry_t *next; - const lxb_css_selector_t *selector; - const lxb_css_selector_anb_of_t *anb; - const lxb_css_selector_pseudo_t *pseudo; - - selector = entry->selector; - - if (selector->type == LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS_FUNCTION) { - pseudo = &selector->u.pseudo; - - /* Optimizing. */ - - switch (pseudo->type) { - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD: - anb = pseudo->data; - - if (anb->of != NULL) { - break; - } - - goto godoit; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE: - goto godoit; - - default: - break; - } - - if (entry->nested == NULL) { - next = lexbor_dobject_calloc(selectors->objs); - if (next == NULL) { - selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION; - return NULL; - } - - next->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - - entry->nested = lexbor_dobject_calloc(selectors->nested); - if (entry->nested == NULL) { - selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION; - return NULL; - } - - entry->nested->entry = next; - entry->nested->parent = selectors->current; - } - - selectors->state = lxb_selectors_state_pseudo_class_function; - selectors->current->last = entry; - selectors->current = entry->nested; - - next = entry->nested->entry; - next->node = entry->node; - - return next; - } - -godoit: - - switch (entry->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - node = lxb_selectors_descendant(selectors, entry, - selector, entry->node); - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - node = lxb_selectors_close(selectors, entry, - selector, entry->node); - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - node = lxb_selectors_child(selectors, entry, - selector, entry->node); - break; - - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - node = lxb_selectors_sibling(selectors, entry, - selector, entry->node); - break; - - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = lxb_selectors_following(selectors, entry, - selector, entry->node); - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CELL: - default: - selectors->status = LXB_STATUS_ERROR; - return NULL; - } - - return lxb_selectors_state_find_check(selectors, node, selector, entry); -} - -static lxb_selectors_entry_t * -lxb_selectors_state_find_check(lxb_selectors_t *selectors, lxb_dom_node_t *node, - const lxb_css_selector_t *selector, - lxb_selectors_entry_t *entry) -{ - lxb_selectors_entry_t *next; - lxb_selectors_nested_t *current; - - if (node == NULL) { - - try_next: - - if (entry->next == NULL) { - - try_next_list: - - if (selector->list->next == NULL) { - return NULL; - } - - /* - * Try the following selectors from the selector list. - */ - - if (entry->following != NULL) { - entry->following->node = entry->node; - - if (selectors->current->parent == NULL) { - selectors->first = entry->following; - } - - return entry->following; - } - - next = lexbor_dobject_calloc(selectors->objs); - if (next == NULL) { - selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION; - return NULL; - } - - next->combinator = LXB_CSS_SELECTOR_COMBINATOR_CLOSE; - next->selector = selector->list->next->last; - next->node = entry->node; - - entry->following = next; - - if (selectors->current->parent == NULL) { - selectors->first = next; - } - - return next; - } - - do { - entry = entry->next; - - while (entry->combinator == LXB_CSS_SELECTOR_COMBINATOR_CLOSE) { - if (entry->next == NULL) { - selector = entry->selector; - goto try_next; - } - - entry = entry->next; - } - - switch (entry->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - node = entry->node->parent; - - if (node == NULL - || node->type != LXB_DOM_NODE_TYPE_ELEMENT) - { - node = NULL; - } - - break; - - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = entry->node->prev; - break; - - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - node = NULL; - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CELL: - default: - selectors->status = LXB_STATUS_ERROR; - return NULL; - } - } - while (node == NULL); - - entry->node = node; - - return entry; - } - - if (selector->prev == NULL) { - current = selectors->current; - - selectors->status = current->cb(current->entry->node, - selector->list->specificity, - current->ctx); - - if ((selectors->options & LXB_SELECTORS_OPT_MATCH_FIRST) == 0 - && current->parent == NULL) - { - if (selectors->status == LXB_STATUS_OK) { - entry = selectors->first; - goto try_next_list; - } - } - - return NULL; - } - - if (entry->prev == NULL) { - next = lexbor_dobject_calloc(selectors->objs); - if (next == NULL) { - selectors->status = LXB_STATUS_ERROR_MEMORY_ALLOCATION; - return NULL; - } - - next->combinator = selector->combinator; - next->selector = selector->prev; - next->node = node; - - next->next = entry; - entry->prev = next; - - return next; - } - - entry->prev->node = node; - - return entry->prev; -} - -static lxb_selectors_entry_t * -lxb_selectors_state_pseudo_class_function(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) -{ - lxb_dom_node_t *node, *base; - lxb_selectors_nested_t *current; - const lxb_css_selector_list_t *list; - lxb_css_selector_anb_of_t *anb; - const lxb_css_selector_pseudo_t *pseudo; - - current = selectors->current; - - base = lxb_selectors_next_node(current); - if (base == NULL) { - goto not_found; - } - - pseudo = ¤t->parent->last->selector->u.pseudo; - - switch (pseudo->type) { - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_HAS: - list = (lxb_css_selector_list_t *) pseudo->data; - node = lxb_selectors_state_has_relative(base, list->first); - - if (node == NULL) { - selectors->current = selectors->current->parent; - entry = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, NULL, - entry->selector, entry); - } - - current->root = base; - - current->entry->selector = list->last; - current->entry->node = node; - current->return_state = lxb_selectors_state_after_find_has; - current->cb = lxb_selectors_cb_ok; - current->ctx = ¤t->found; - current->found = false; - - selectors->state = lxb_selectors_state_find; - - return entry; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_CURRENT: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_IS: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_WHERE: - current->entry->selector = ((lxb_css_selector_list_t *) pseudo->data)->last; - current->entry->node = base; - current->return_state = lxb_selectors_state_after_find; - current->cb = lxb_selectors_cb_ok; - current->ctx = ¤t->found; - current->found = false; - - selectors->state = lxb_selectors_state_find; - - return entry; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NOT: - current->entry->selector = ((lxb_css_selector_list_t *) pseudo->data)->last; - current->entry->node = base; - current->return_state = lxb_selectors_state_after_find; - current->cb = lxb_selectors_cb_not; - current->ctx = ¤t->found; - current->found = true; - - selectors->state = lxb_selectors_state_find; - - return entry; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD: - anb = pseudo->data; - - current->entry->selector = anb->of->last; - current->entry->node = base; - current->return_state = lxb_selectors_state_after_nth_child; - current->cb = lxb_selectors_cb_ok; - current->ctx = ¤t->found; - current->root = base; - current->index = 0; - current->found = false; - - selectors->state = lxb_selectors_state_find; - - return entry; - - /* - * This one can only happen if the user has somehow messed up the - * selector. - */ - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL: - default: - break; - } - -not_found: - - selectors->current = selectors->current->parent; - entry = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, NULL, - entry->selector, entry); -} - -static lxb_dom_node_t * -lxb_selectors_next_node(lxb_selectors_nested_t *main) -{ - lxb_dom_node_t *node = main->entry->node; - - switch (main->parent->last->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - if (node->parent == NULL - || node->parent->type != LXB_DOM_NODE_TYPE_ELEMENT) - { - return NULL; - } - - return node->parent; - - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - return node; - - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->prev; - break; - - default: - return NULL; - } - - while (node != NULL) { - if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) { - break; - } - - node = node->prev; - } - - return node; -} - -static lxb_dom_node_t * -lxb_selectors_state_has_relative(lxb_dom_node_t *node, - const lxb_css_selector_t *selector) -{ - lxb_dom_node_t *root = node; - - switch (selector->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - node = node->first_child; - break; - - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->next; - break; - - default: - return NULL; - } - - while (node != NULL) { - if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) { - break; - } - - while (node !=root && node->next == NULL && node->parent != NULL) { - node = node->parent; - } - - if (node == root) { - return NULL; - } - - node = node->next; - } - - return node; -} - -static lxb_selectors_entry_t * -lxb_selectors_state_after_find_has(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) -{ - lxb_dom_node_t *node; - lxb_selectors_entry_t *parent; - lxb_selectors_nested_t *current; - - if (selectors->current->found) { - node = selectors->current->root; - - selectors->current = selectors->current->parent; - parent = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); - } - - current = selectors->current; - node = entry->node; - - switch (entry->selector->list->first->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - if (node->first_child != NULL) { - node = node->first_child; - } - else { - - next: - - while (node != current->root && node->next == NULL) { - node = node->parent; - } - - if (node == current->root) { - goto failed; - } - - node = node->next; - } - - if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) { - goto next; - } - - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->next; - - while (node != NULL && node->type != LXB_DOM_NODE_TYPE_ELEMENT) { - node = node->next; - } - - if (node == NULL) { - goto failed; - } - - break; - - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - goto failed; - - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - case LXB_CSS_SELECTOR_COMBINATOR_CELL: - default: - selectors->status = LXB_STATUS_ERROR; - return NULL; - } - - entry->node = node; - selectors->state = lxb_selectors_state_find; - - return entry; - -failed: - - selectors->current = selectors->current->parent; - parent = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, NULL, - parent->selector, parent); -} - - -static lxb_selectors_entry_t * -lxb_selectors_state_after_find(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) -{ - lxb_dom_node_t *node; - lxb_selectors_entry_t *parent; - lxb_selectors_nested_t *current; - - current = selectors->current; - - if (current->found) { - node = entry->node; - - selectors->current = current->parent; - parent = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); - } - - node = entry->node; - - switch (current->parent->last->combinator) { - case LXB_CSS_SELECTOR_COMBINATOR_DESCENDANT: - if (node->parent != NULL - && node->parent->type == LXB_DOM_NODE_TYPE_ELEMENT) - { - node = node->parent; - } - else { - node = NULL; - } - - break; - - case LXB_CSS_SELECTOR_COMBINATOR_FOLLOWING: - node = node->prev; - - while (node != NULL && node->type != LXB_DOM_NODE_TYPE_ELEMENT) { - node = node->prev; - } - - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CHILD: - case LXB_CSS_SELECTOR_COMBINATOR_SIBLING: - case LXB_CSS_SELECTOR_COMBINATOR_CLOSE: - node = NULL; - break; - - case LXB_CSS_SELECTOR_COMBINATOR_CELL: - default: - selectors->status = LXB_STATUS_ERROR; - return NULL; - } - - if (node == NULL) { - selectors->current = current->parent; - parent = selectors->current->last; - - selectors->state = lxb_selectors_state_find; - - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); - } - - entry->node = node; - selectors->state = lxb_selectors_state_find; - - return entry; -} - -static lxb_selectors_entry_t * -lxb_selectors_state_after_nth_child(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry) -{ - bool found; - lxb_dom_node_t *node; - lxb_selectors_entry_t *parent; - lxb_selectors_nested_t *current; - const lxb_css_selector_t *selector; - const lxb_css_selector_pseudo_t *pseudo; - - current = selectors->current; - selector = current->parent->last->selector; - pseudo = &selector->u.pseudo; - - node = entry->node; - - if (current->found) { - current->index += 1; - } - else if (current->root == node) { - node = NULL; - goto done; - } - - if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD) { - node = node->prev; - - while (node != NULL) { - if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) { - break; - } - - node = node->prev; - } - } - else { - node = node->next; - - while (node != NULL) { - if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) { - break; - } - - node = node->next; - } - } - - if (node == NULL) { - goto done; - } - - entry->node = node; - current->found = false; - selectors->state = lxb_selectors_state_find; - - return entry; - -done: - - if (current->index > 0) { - found = lxb_selectors_anb_calc(pseudo->data, current->index); - - node = (found) ? current->root : NULL; - } - - selectors->state = lxb_selectors_state_find; - selectors->current = selectors->current->parent; - - parent = selectors->current->last; - - return lxb_selectors_state_find_check(selectors, node, - parent->selector, parent); -} - -static bool -lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry, - const lxb_css_selector_t *selector, lxb_dom_node_t *node) -{ - lxb_dom_element_t *element; - - switch (selector->type) { - case LXB_CSS_SELECTOR_TYPE_ANY: - return true; - - case LXB_CSS_SELECTOR_TYPE_ELEMENT: - return lxb_selectors_match_element(selector, node, entry); - - case LXB_CSS_SELECTOR_TYPE_ID: - return lxb_selectors_match_id(selector, node); - - case LXB_CSS_SELECTOR_TYPE_CLASS: - element = lxb_dom_interface_element(node); - - if (element->attr_class == NULL - || element->attr_class->value == NULL) - { - return false; - } - - return lxb_selectors_match_class(element->attr_class->value, - &selector->name, true); - - case LXB_CSS_SELECTOR_TYPE_ATTRIBUTE: - return lxb_selectors_match_attribute(selector, node, entry); - - case LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS: - return lxb_selectors_pseudo_class(selector, node); - - case LXB_CSS_SELECTOR_TYPE_PSEUDO_CLASS_FUNCTION: - return lxb_selectors_pseudo_class_function(selector, node); - - case LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT: - return lxb_selectors_pseudo_element(selector, node); - - case LXB_CSS_SELECTOR_TYPE_PSEUDO_ELEMENT_FUNCTION: - return false; - - default: - break; - } - - return false; -} - -static bool -lxb_selectors_match_element(const lxb_css_selector_t *selector, - lxb_dom_node_t *node, lxb_selectors_entry_t *entry) -{ - lxb_tag_id_t tag_id; - - if (entry->id == 0) { - tag_id = lxb_tag_id_by_name(node->owner_document->tags, - selector->name.data, selector->name.length); - if (tag_id == LXB_TAG__UNDEF) { - return false; - } - - entry->id = tag_id; - } - - return node->local_name == entry->id; -} - -static bool -lxb_selectors_match_id(const lxb_css_selector_t *selector, lxb_dom_node_t *node) -{ - const lexbor_str_t *trg, *src; - lxb_dom_element_t *element; - - element = lxb_dom_interface_element(node); - - if (element->attr_id == NULL || element->attr_id->value == NULL) { - return false; - } - - trg = element->attr_id->value; - src = &selector->name; - - return trg->length == src->length - && lexbor_str_data_ncasecmp(trg->data, src->data, src->length); -} - -static bool -lxb_selectors_match_class(const lexbor_str_t *target, const lexbor_str_t *src, - bool quirks) -{ - lxb_char_t chr; - - if (target->length < src->length) { - return false; - } - - bool is_it = false; - - const lxb_char_t *data = target->data; - const lxb_char_t *pos = data; - const lxb_char_t *end = data + target->length; - - for (; data < end; data++) { - chr = *data; - - if (lexbor_utils_whitespace(chr, ==, ||)) { - - if ((size_t) (data - pos) == src->length) { - if (quirks) { - is_it = lexbor_str_data_ncasecmp(pos, src->data, src->length); - } - else { - is_it = lexbor_str_data_ncmp(pos, src->data, src->length); - } - - if (is_it) { - return true; - } - } - - if ((size_t) (end - data) < src->length) { - return false; - } - - pos = data + 1; - } - } - - if ((size_t) (end - pos) == src->length && src->length != 0) { - if (quirks) { - is_it = lexbor_str_data_ncasecmp(pos, src->data, src->length); - } - else { - is_it = lexbor_str_data_ncmp(pos, src->data, src->length); - } - } - - return is_it; -} - -static bool -lxb_selectors_match_attribute(const lxb_css_selector_t *selector, - lxb_dom_node_t *node, lxb_selectors_entry_t *entry) -{ - bool res, ins; - lxb_dom_attr_t *dom_attr; - lxb_dom_element_t *element; - const lexbor_str_t *trg, *src; - const lxb_dom_attr_data_t *attr_data; - const lxb_css_selector_attribute_t *attr; - - static const lexbor_str_t lxb_blank_str = { - .data = (lxb_char_t *) "", - .length = 0 - }; - - element = lxb_dom_interface_element(node); - attr = &selector->u.attribute; - - if (entry->id == 0) { - attr_data = lxb_dom_attr_data_by_local_name(node->owner_document->attrs, - selector->name.data, selector->name.length); - if (attr_data == NULL) { - return false; - } - - entry->id = attr_data->attr_id; - } - - dom_attr = lxb_dom_element_attr_by_id(element, entry->id); - if (dom_attr == NULL) { - return false; - } - - trg = dom_attr->value; - src = &attr->value; - - if (src->data == NULL) { - return true; - } - - if (trg == NULL) { - trg = &lxb_blank_str; - } - - ins = attr->modifier == LXB_CSS_SELECTOR_MODIFIER_I; - - switch (attr->match) { - case LXB_CSS_SELECTOR_MATCH_EQUAL: /* = */ - if (trg->length == src->length) { - if (ins) { - return lexbor_str_data_ncasecmp(trg->data, src->data, - src->length); - } - - return lexbor_str_data_ncmp(trg->data, src->data, - src->length); - } - - return false; - - case LXB_CSS_SELECTOR_MATCH_INCLUDE: /* ~= */ - return lxb_selectors_match_class(trg, src, ins); - - case LXB_CSS_SELECTOR_MATCH_DASH: /* |= */ - if (trg->length == src->length) { - if (ins) { - return lexbor_str_data_ncasecmp(trg->data, src->data, - src->length); - } - - return lexbor_str_data_ncmp(trg->data, src->data, - src->length); - } - - if (trg->length > src->length) { - if (ins) { - res = lexbor_str_data_ncasecmp(trg->data, - src->data, src->length); - } - else { - res = lexbor_str_data_ncmp(trg->data, - src->data, src->length); - } - - if (res && trg->data[src->length] == '-') { - return true; - } - } - - return false; - - case LXB_CSS_SELECTOR_MATCH_PREFIX: /* ^= */ - if (src->length != 0 && trg->length >= src->length) { - if (ins) { - return lexbor_str_data_ncasecmp(trg->data, src->data, - src->length); - } - - return lexbor_str_data_ncmp(trg->data, src->data, - src->length); - } - - return false; - - case LXB_CSS_SELECTOR_MATCH_SUFFIX: /* $= */ - if (src->length != 0 && trg->length >= src->length) { - size_t dif = trg->length - src->length; - - if (ins) { - return lexbor_str_data_ncasecmp(trg->data + dif, - src->data, src->length); - } - - return lexbor_str_data_ncmp(trg->data + dif, src->data, - src->length); - } - - return false; - - case LXB_CSS_SELECTOR_MATCH_SUBSTRING: /* *= */ - if (src->length == 0) { - return false; - } - - if (ins) { - return lexbor_str_data_ncasecmp_contain(trg->data, trg->length, - src->data, src->length); - } - - return lexbor_str_data_ncmp_contain(trg->data, trg->length, - src->data, src->length); - default: - break; - } - - return false; -} - -static bool -lxb_selectors_pseudo_class(const lxb_css_selector_t *selector, - const lxb_dom_node_t *node) -{ - lexbor_str_t *str; - lxb_dom_attr_t *attr; - const lxb_dom_node_t *root; - const lxb_css_selector_pseudo_t *pseudo = &selector->u.pseudo; - - static const lxb_char_t checkbox[] = "checkbox"; - static const size_t checkbox_length = sizeof(checkbox) / sizeof(lxb_char_t) - 1; - - static const lxb_char_t radio[] = "radio"; - static const size_t radio_length = sizeof(radio) / sizeof(lxb_char_t) - 1; - - switch (pseudo->type) { - case LXB_CSS_SELECTOR_PSEUDO_CLASS_ACTIVE: - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_ACTIVE); - return attr != NULL; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_ANY_LINK: - if(node->local_name == LXB_TAG_A || - node->local_name == LXB_TAG_AREA || - node->local_name == LXB_TAG_MAP) - { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_HREF); - return attr != NULL; - } - - return false; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_BLANK: - return lxb_dom_node_is_empty(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_CHECKED: - if (node->local_name == LXB_TAG_INPUT) { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_TYPE); - if (attr == NULL) { - return false; - } - - if (attr->value == NULL) { - return false; - } - - str = attr->value; - - if(str->length == 8) { - if (lexbor_str_data_ncasecmp(checkbox, str->data, checkbox_length)) { - goto check; - } - } - else if(str->length == 5) { - if (lexbor_str_data_ncasecmp(radio, str->data, radio_length)) { - goto check; - } - } - } - else if(node->local_name == LXB_TAG_OPTION) { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_SELECTED); - if (attr != NULL) { - return true; - } - } - else if(node->local_name >= LXB_TAG__LAST_ENTRY) { - goto check; - } - - return false; - - check: - - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_CHECKED); - if (attr != NULL) { - return true; - } - - return false; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_CURRENT: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_DEFAULT: - return false; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_DISABLED: - return lxb_selectors_pseudo_class_disabled(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_EMPTY: - root = node; - node = node->first_child; - - while (node != NULL) { - if (node->local_name != LXB_TAG__EM_COMMENT) { - return false; - } - - if (node->first_child != NULL) { - node = node->first_child; - } - else { - while (node != root && node->next == NULL) { - node = node->parent; - } - - if (node == root) { - break; - } - - node = node->next; - } - } - - return true; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_ENABLED: - return !lxb_selectors_pseudo_class_disabled(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FIRST_CHILD: - return lxb_selectors_pseudo_class_first_child(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FIRST_OF_TYPE: - return lxb_selectors_pseudo_class_first_of_type(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FOCUS: - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_FOCUS); - return attr != NULL; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FOCUS_VISIBLE: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FOCUS_WITHIN: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FULLSCREEN: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUTURE: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_HOVER: - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_HOVER); - return attr != NULL; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_IN_RANGE: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_INDETERMINATE: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_INVALID: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_LAST_CHILD: - return lxb_selectors_pseudo_class_last_child(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_LAST_OF_TYPE: - return lxb_selectors_pseudo_class_last_of_type(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_LINK: - if (node->local_name == LXB_TAG_A - || node->local_name == LXB_TAG_AREA - || node->local_name == LXB_TAG_LINK) - { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_HREF); - return attr != NULL; - } - - return false; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_LOCAL_LINK: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_ONLY_CHILD: - return lxb_selectors_pseudo_class_first_child(node) - && lxb_selectors_pseudo_class_last_child(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_ONLY_OF_TYPE: - return lxb_selectors_pseudo_class_first_of_type(node) - && lxb_selectors_pseudo_class_last_of_type(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_OPTIONAL: - if (node->local_name == LXB_TAG_INPUT - || node->local_name == LXB_TAG_SELECT - || node->local_name == LXB_TAG_TEXTAREA) - { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_REQUIRED); - return attr == NULL; - } - - return false; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_OUT_OF_RANGE: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_PAST: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_PLACEHOLDER_SHOWN: - if (node->local_name == LXB_TAG_INPUT - || node->local_name == LXB_TAG_TEXTAREA) - { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_PLACEHOLDER); - return attr != NULL; - } - - return false; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_READ_ONLY: - return !lxb_selectors_pseudo_class_read_write(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_READ_WRITE: - return lxb_selectors_pseudo_class_read_write(node); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_REQUIRED: - if (node->local_name == LXB_TAG_INPUT - || node->local_name == LXB_TAG_SELECT - || node->local_name == LXB_TAG_TEXTAREA) - { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_REQUIRED); - return attr != NULL; - } - - return false; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_ROOT: - return lxb_dom_document_root(node->owner_document) == node; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_SCOPE: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_TARGET: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_TARGET_WITHIN: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_USER_INVALID: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_VALID: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_VISITED: - break; - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_WARNING: - break; - } - - return false; -} - -static bool -lxb_selectors_pseudo_class_function(const lxb_css_selector_t *selector, - lxb_dom_node_t *node) -{ - size_t index; - lxb_dom_node_t *base; - const lxb_css_selector_pseudo_t *pseudo; - - pseudo = &selector->u.pseudo; - - switch (pseudo->type) { - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD: - index = 0; - - if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_CHILD) { - while (node != NULL) { - if (node->local_name != LXB_TAG__TEXT - && node->local_name != LXB_TAG__EM_COMMENT) - { - index++; - } - - node = node->prev; - } - } - else { - while (node != NULL) { - if (node->local_name != LXB_TAG__TEXT - && node->local_name != LXB_TAG__EM_COMMENT) - { - index++; - } - - node = node->next; - } - } - - return lxb_selectors_anb_calc(pseudo->data, index); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE: - index = 0; - base = node; - - if (pseudo->type == LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE) { - while (node != NULL) { - if(node->local_name == base->local_name - && node->ns == base->ns) - { - index++; - } - - node = node->prev; - } - } - else { - while (node != NULL) { - if(node->local_name == base->local_name - && node->ns == base->ns) - { - index++; - } - - node = node->next; - } - } - - return lxb_selectors_anb_calc(pseudo->data, index); - - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_DIR: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_LANG: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_COL: - case LXB_CSS_SELECTOR_PSEUDO_CLASS_FUNCTION_NTH_LAST_COL: - default: - break; - } - - return false; -} - -static bool -lxb_selectors_pseudo_element(const lxb_css_selector_t *selector, - const lxb_dom_node_t *node) -{ - const lxb_css_selector_pseudo_t *pseudo = &selector->u.pseudo; - - switch (pseudo->type) { - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_AFTER: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_BACKDROP: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_BEFORE: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_FIRST_LETTER: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_FIRST_LINE: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_GRAMMAR_ERROR: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_INACTIVE_SELECTION: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_MARKER: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_PLACEHOLDER: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_SELECTION: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_SPELLING_ERROR: - case LXB_CSS_SELECTOR_PSEUDO_ELEMENT_TARGET_TEXT: - break; - } - - return false; -} - -static bool -lxb_selectors_pseudo_class_disabled(const lxb_dom_node_t *node) -{ - lxb_dom_attr_t *attr; - uintptr_t tag_id = node->local_name; - - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_DISABLED); - if (attr == NULL) { - return false; - } - - if (tag_id == LXB_TAG_BUTTON || tag_id == LXB_TAG_INPUT || - tag_id == LXB_TAG_SELECT || tag_id == LXB_TAG_TEXTAREA || - tag_id >= LXB_TAG__LAST_ENTRY) - { - return true; - } - - node = node->parent; - - while (node != NULL) { - if (node->local_name == LXB_TAG_FIELDSET - && node->first_child->local_name != LXB_TAG_LEGEND) - { - return true; - } - - node = node->parent; - } - - return false; -} - -static bool -lxb_selectors_pseudo_class_first_child(const lxb_dom_node_t *node) -{ - node = node->prev; - - while (node != NULL) { - if (node->local_name != LXB_TAG__TEXT - && node->local_name != LXB_TAG__EM_COMMENT) - { - return false; - } - - node = node->prev; - } - - return true; -} - -static bool -lxb_selectors_pseudo_class_first_of_type(const lxb_dom_node_t *node) -{ - const lxb_dom_node_t *root = node; - node = node->prev; - - while (node) { - if (node->local_name == root->local_name - && node->ns == root->ns) - { - return false; - } - - node = node->prev; - } - - return true; -} - -static bool -lxb_selectors_pseudo_class_last_child(const lxb_dom_node_t *node) -{ - node = node->next; - - while (node != NULL) { - if (node->local_name != LXB_TAG__TEXT - && node->local_name != LXB_TAG__EM_COMMENT) - { - return false; - } - - node = node->next; - } - - return true; -} - -static bool -lxb_selectors_pseudo_class_last_of_type(const lxb_dom_node_t *node) -{ - const lxb_dom_node_t *root = node; - node = node->next; - - while (node) { - if (node->local_name == root->local_name - && node->ns == root->ns) - { - return false; - } - - node = node->next; - } - - return true; -} - -static bool -lxb_selectors_pseudo_class_read_write(const lxb_dom_node_t *node) -{ - lxb_dom_attr_t *attr; - - if (node->local_name == LXB_TAG_INPUT - || node->local_name == LXB_TAG_TEXTAREA) - { - attr = lxb_dom_element_attr_by_id(lxb_dom_interface_element(node), - LXB_DOM_ATTR_READONLY); - if (attr != NULL) { - return false; - } - - return !lxb_selectors_pseudo_class_disabled(node); - } - - return false; -} - -static bool -lxb_selectors_anb_calc(lxb_css_selector_anb_of_t *anb, size_t index) -{ - double num; - - if (anb->anb.a == 0) { - if (anb->anb.b >= 0 && (size_t) anb->anb.b == index) { - return true; - } - } - else { - num = ((double) index - (double) anb->anb.b) / (double) anb->anb.a; - - if (num >= 0.0f && (num - trunc(num)) == 0.0f) { - return true; - } - } - - return false; -} - -static lxb_status_t -lxb_selectors_cb_ok(lxb_dom_node_t *node, - lxb_css_selector_specificity_t spec, void *ctx) -{ - *((bool *) ctx) = true; - return LXB_STATUS_OK; -} - -static lxb_status_t -lxb_selectors_cb_not(lxb_dom_node_t *node, - lxb_css_selector_specificity_t spec, void *ctx) -{ - *((bool *) ctx) = false; - return LXB_STATUS_OK; -} - -void -lxb_selectors_opt_set_noi(lxb_selectors_t *selectors, lxb_selectors_opt_t opt) -{ - lxb_selectors_opt_set(selectors, opt); -} - -const lxb_css_selector_list_t * -lxb_selectors_selector_noi(const lxb_selectors_t *selectors) -{ - return lxb_selectors_selector(selectors); -} diff --git a/ext/lexbor/lexbor/selectors/selectors.h b/ext/lexbor/lexbor/selectors/selectors.h deleted file mode 100644 index a9db864ff17fb..0000000000000 --- a/ext/lexbor/lexbor/selectors/selectors.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2021-2024 Alexander Borisov - * - * Author: Alexander Borisov - */ - - -#ifndef LEXBOR_SELECTORS_H -#define LEXBOR_SELECTORS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "lexbor/selectors/base.h" -#include "lexbor/dom/dom.h" -#include "lexbor/css/selectors/selectors.h" -#include "lexbor/core/array_obj.h" - - -typedef enum { - LXB_SELECTORS_OPT_DEFAULT = 0x00, - - /* - * Includes the passed (root) node in the search. - * - * By default, the root node does not participate in selector searches, - * only its children. - * - * This behavior is logical, if you have found a node and then you want to - * search for other nodes in it, you don't need to check it again. - * - * But there are cases when it is necessary for root node to participate - * in the search. That's what this option is for. - */ - LXB_SELECTORS_OPT_MATCH_ROOT = 1 << 1, - - /* - * Stop searching after the first match with any of the selectors - * in the list. - * - * By default, the callback will be triggered for each selector list. - * That is, if your node matches different selector lists, it will be - * returned multiple times in the callback. - * - * For example: - * HTML:
test
- * Selectors: div, div[id="ok"], div:has(:not(a)) - * - * The default behavior will cause three callbacks with the same node (div). - * Because it will be found by every selector in the list. - * - * This option allows you to end the element check after the first match on - * any of the selectors. That is, the callback will be called only once - * for example above. This way we get rid of duplicates in the search. - */ - LXB_SELECTORS_OPT_MATCH_FIRST = 1 << 2 -} -lxb_selectors_opt_t; - -typedef struct lxb_selectors lxb_selectors_t; -typedef struct lxb_selectors_entry lxb_selectors_entry_t; -typedef struct lxb_selectors_nested lxb_selectors_nested_t; - -typedef lxb_status_t -(*lxb_selectors_cb_f)(lxb_dom_node_t *node, - lxb_css_selector_specificity_t spec, void *ctx); - -typedef lxb_selectors_entry_t * -(*lxb_selectors_state_cb_f)(lxb_selectors_t *selectors, - lxb_selectors_entry_t *entry); - -struct lxb_selectors_entry { - uintptr_t id; - lxb_css_selector_combinator_t combinator; - const lxb_css_selector_t *selector; - lxb_dom_node_t *node; - lxb_selectors_entry_t *next; - lxb_selectors_entry_t *prev; - lxb_selectors_entry_t *following; - lxb_selectors_nested_t *nested; -}; - -struct lxb_selectors_nested { - lxb_selectors_entry_t *entry; - lxb_selectors_state_cb_f return_state; - - lxb_selectors_cb_f cb; - void *ctx; - - lxb_dom_node_t *root; - lxb_selectors_entry_t *last; - lxb_selectors_nested_t *parent; - - size_t index; - bool found; -}; - -struct lxb_selectors { - lxb_selectors_state_cb_f state; - lexbor_dobject_t *objs; - lexbor_dobject_t *nested; - - lxb_selectors_nested_t *current; - lxb_selectors_entry_t *first; - - lxb_selectors_opt_t options; - lxb_status_t status; -}; - - -/* - * Create lxb_selectors_t object. - * - * @return lxb_selectors_t * if successful, otherwise NULL. - */ -LXB_API lxb_selectors_t * -lxb_selectors_create(void); - -/* - * Initialization of lxb_selectors_t object. - * - * Caches are initialized in this function. - * - * @param[in] lxb_selectors_t * - * - * @return LXB_STATUS_OK if successful, otherwise an error status value. - */ -LXB_API lxb_status_t -lxb_selectors_init(lxb_selectors_t *selectors); - -/* - * Clears the object. Returns object to states as after initialization. - * - * After each call to lxb_selectors_find() and lxb_selectors_find_for_node(), - * the lxb_selectors_t object is cleared. That is, you don't need to call this - * function every time after searching by a selector. - * - * @param[in] lxb_url_parser_t * - */ -LXB_API void -lxb_selectors_clean(lxb_selectors_t *selectors); - -/* - * Destroy lxb_selectors_t object. - * - * Destroying all caches. - * - * @param[in] lxb_selectors_t *. Can be NULL. - * @param[in] if false: only destroys internal caches. - * if true: destroys the lxb_selectors_t object and all internal caches. - * - * @return lxb_selectors_t * if self_destroy = false, otherwise NULL. - */ -LXB_API lxb_selectors_t * -lxb_selectors_destroy(lxb_selectors_t *selectors, bool self_destroy); - -/* - * Search for nodes by selector list. - * - * Default Behavior: - * 1. The root node does not participate in the search, only its child nodes. - * 2. If a node matches multiple selector lists, a callback with that node - * will be called on each list. - * For example: - * HTML:
- * Selectors: div, div[id="ok"], div:has(:not(a)) - * For each selector list, a callback with a "div" node will be called. - * - * To change the search behavior, see lxb_selectors_opt_set(). - * - * @param[in] lxb_selectors_t *. - * @param[in] lxb_dom_node_t *. The node from which the search will begin. - * @param[in] const lxb_css_selector_list_t *. Selectors List. - * @param[in] lxb_selectors_cb_f. Callback for a found node. - * @param[in] void *. Context for the callback. - * if true: destroys the lxb_selectors_t object and all internal caches. - * - * @return LXB_STATUS_OK if successful, otherwise an error status value. - */ -LXB_API lxb_status_t -lxb_selectors_find(lxb_selectors_t *selectors, lxb_dom_node_t *root, - const lxb_css_selector_list_t *list, - lxb_selectors_cb_f cb, void *ctx); - -/* - * Match a node to a Selectors List. - * - * In other words, the function checks which selector lists will find the - * specified node. - * - * Default Behavior: - * 1. If a node matches multiple selector lists, a callback with that node - * will be called on each list. - * For example: - * HTML:
- * Node: div - * Selectors: div, div[id="ok"], div:has(:not(a)) - * For each selector list, a callback with a "div" node will be called. - * - * To change the search behavior, see lxb_selectors_opt_set(). - * - * @param[in] lxb_selectors_t *. - * @param[in] lxb_dom_node_t *. The node from which the search will begin. - * @param[in] const lxb_css_selector_list_t *. Selectors List. - * @param[in] lxb_selectors_cb_f. Callback for a found node. - * @param[in] void *. Context for the callback. - * if true: destroys the lxb_selectors_t object and all internal caches. - * - * @return LXB_STATUS_OK if successful, otherwise an error status value. - */ -LXB_API lxb_status_t -lxb_selectors_match_node(lxb_selectors_t *selectors, lxb_dom_node_t *node, - const lxb_css_selector_list_t *list, - lxb_selectors_cb_f cb, void *ctx); - -/* - * Deprecated! - * This function does exactly the same thing as lxb_selectors_match_node(). - */ -LXB_API LXB_DEPRECATED(lxb_status_t -lxb_selectors_find_reverse(lxb_selectors_t *selectors, lxb_dom_node_t *root, - lxb_css_selector_list_t *list, - lxb_selectors_cb_f cb, void *ctx)); - -/* - * Inline functions. - */ - -/* - * The function sets the node search options. - * - * For more information, see lxb_selectors_opt_t. - * - * @param[in] lxb_selectors_t *. - * @param[in] lxb_selectors_opt_t. - */ -lxb_inline void -lxb_selectors_opt_set(lxb_selectors_t *selectors, lxb_selectors_opt_t opt) -{ - selectors->options = opt; -} - -/* - * Get the current selector. - * - * Function to get the selector by which the node was found. - * Use context (void *ctx) to pass the lxb_selectors_t object to the callback. - * - * @param[in] const lxb_selectors_t *. - * - * @return const lxb_css_selector_list_t *. - */ -lxb_inline const lxb_css_selector_list_t * -lxb_selectors_selector(const lxb_selectors_t *selectors) -{ - return selectors->current->entry->selector->list; -} - -/* - * Not inline for inline. - */ - -/* - * Same as lxb_selectors_opt_set() function, but not inline. - */ -LXB_API void -lxb_selectors_opt_set_noi(lxb_selectors_t *selectors, lxb_selectors_opt_t opt); - -/* - * Same as lxb_selectors_selector() function, but not inline. - */ -LXB_API const lxb_css_selector_list_t * -lxb_selectors_selector_noi(const lxb_selectors_t *selectors); - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LEXBOR_SELECTORS_H */ diff --git a/ext/lexbor/lexbor/url/url.c b/ext/lexbor/lexbor/url/url.c index bbb3b5bbd3cb7..9185d77d35438 100644 --- a/ext/lexbor/lexbor/url/url.c +++ b/ext/lexbor/lexbor/url/url.c @@ -1818,7 +1818,7 @@ lxb_url_parse_basic_h(lxb_url_parser_t *parser, lxb_url_t *url, } if (override_state == LXB_URL_STATE_HOSTNAME_STATE) { - lxb_url_parse_return(orig_data, buf, LXB_STATUS_OK); + lxb_url_parse_return(orig_data, buf, LXB_STATUS_ERROR); } status = lxb_url_host_parse(parser, begin, p, &url->host, @@ -4804,7 +4804,7 @@ lxb_url_serialize_fragment(const lxb_url_t *url, } lxb_url_t * -lxb_url_clone(lexbor_mraw_t *mraw, lxb_url_t *url) +lxb_url_clone(lexbor_mraw_t *mraw, const lxb_url_t *url) { lxb_status_t status; lxb_url_t *new_url; diff --git a/ext/lexbor/lexbor/url/url.h b/ext/lexbor/lexbor/url/url.h index 58952a0f910b6..b1a9a6f013eb6 100644 --- a/ext/lexbor/lexbor/url/url.h +++ b/ext/lexbor/lexbor/url/url.h @@ -463,7 +463,7 @@ lxb_url_serialize_fragment(const lxb_url_t *url, * @return a new URL object if successful, otherwise NULL value. */ LXB_API lxb_url_t * -lxb_url_clone(lexbor_mraw_t *mraw, lxb_url_t *url); +lxb_url_clone(lexbor_mraw_t *mraw, const lxb_url_t *url); /* * Inline functions. diff --git a/ext/libxml/config.w32 b/ext/libxml/config.w32 index cc5f284dbc1c1..2362ea0c2ba31 100644 --- a/ext/libxml/config.w32 +++ b/ext/libxml/config.w32 @@ -11,7 +11,7 @@ if (PHP_LIBXML == "yes") { if (GREP_HEADER("libxml/xmlversion.h", "#define\\s+LIBXML_VERSION\\s+(\\d+)", PHP_PHP_BUILD + "\\include\\libxml2") && +RegExp.$1 >= 20904) { - EXTENSION("libxml", "libxml.c mime_sniff.c", false /* never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + EXTENSION("libxml", "libxml.c mime_sniff.c image_svg.c", false /* never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); AC_DEFINE("HAVE_LIBXML", 1, "Define to 1 if the PHP extension 'libxml' is available."); ADD_FLAG("CFLAGS_LIBXML", "/D LIBXML_STATIC /D LIBXML_STATIC_FOR_DLL /D HAVE_WIN32_THREADS "); if (!PHP_LIBXML_SHARED) { diff --git a/ext/libxml/config0.m4 b/ext/libxml/config0.m4 index 67ffa9a78ce44..5b400751d1b50 100644 --- a/ext/libxml/config0.m4 +++ b/ext/libxml/config0.m4 @@ -12,7 +12,7 @@ if test "$PHP_LIBXML" != "no"; then AC_DEFINE([HAVE_LIBXML], [1], [Define to 1 if the PHP extension 'libxml' is available.]) PHP_NEW_EXTENSION([libxml], - [libxml.c mime_sniff.c], + [libxml.c mime_sniff.c image_svg.c], [$ext_shared],, [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) PHP_INSTALL_HEADERS([ext/libxml], [php_libxml.h]) diff --git a/ext/libxml/image_svg.c b/ext/libxml/image_svg.c new file mode 100644 index 0000000000000..091f7e283168e --- /dev/null +++ b/ext/libxml/image_svg.c @@ -0,0 +1,178 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Niels Dossche | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "image_svg.h" +#include "php_libxml.h" + +#include "ext/standard/php_image.h" + +#include + +#ifdef HAVE_LIBXML + +static int svg_image_type_id; + +static int php_libxml_svg_stream_read(void *context, char *buffer, int len) +{ + return php_stream_read(context, buffer, len); +} + +/* Sanity check that the input only contains characters valid for a dimension (numbers with units, e.g. 5cm). + * This also protects the user against injecting XSS. + * Only accept [0-9]+[a-zA-Z]* */ +static bool php_libxml_parse_dimension(const xmlChar *input, const xmlChar **unit_position) +{ + if (!(*input >= '0' && *input <= '9')) { + return false; + } + + input++; + + while (*input) { + if (!(*input >= '0' && *input <= '9')) { + if ((*input >= 'a' && *input <= 'z') || (*input >= 'A' && *input <= 'Z')) { + break; + } + return false; + } + input++; + } + + *unit_position = input; + + while (*input) { + if (!((*input >= 'a' && *input <= 'z') || (*input >= 'A' && *input <= 'Z'))) { + return false; + } + input++; + } + + return true; +} + +zend_result php_libxml_svg_image_handle(php_stream *stream, struct php_gfxinfo **result) +{ + if (php_stream_rewind(stream)) { + return FAILURE; + } + + /* Early check before doing more expensive work */ + if (php_stream_getc(stream) != '<') { + return FAILURE; + } + + if (php_stream_rewind(stream)) { + return FAILURE; + } + + PHP_LIBXML_SANITIZE_GLOBALS(reader_for_stream); + xmlTextReaderPtr reader = xmlReaderForIO( + php_libxml_svg_stream_read, + NULL, + stream, + NULL, + NULL, + XML_PARSE_NOWARNING | XML_PARSE_NOERROR | XML_PARSE_NONET + ); + PHP_LIBXML_RESTORE_GLOBALS(reader_for_stream); + + if (!reader) { + return FAILURE; + } + + bool is_svg = false; + while (xmlTextReaderRead(reader) == 1) { + if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { + /* Root must be an svg element */ + const xmlChar *name = xmlTextReaderConstLocalName(reader); + if (!name || strcasecmp((const char *) name, "svg") != 0) { + break; + } + + xmlChar *width = xmlTextReaderGetAttribute(reader, BAD_CAST "width"); + xmlChar *height = xmlTextReaderGetAttribute(reader, BAD_CAST "height"); + const xmlChar *width_unit_position, *height_unit_position; + if (!width || !height + || !php_libxml_parse_dimension(width, &width_unit_position) + || !php_libxml_parse_dimension(height, &height_unit_position)) { + xmlFree(width); + xmlFree(height); + break; + } + + is_svg = true; + if (result) { + *result = ecalloc(1, sizeof(**result)); + (*result)->width = ZEND_STRTOL((const char *) width, NULL, 10); + (*result)->height = ZEND_STRTOL((const char *) height, NULL, 10); + if (*width_unit_position) { + (*result)->width_unit = zend_string_init((const char*) width_unit_position, + xmlStrlen(width_unit_position), false); + } + if (*height_unit_position) { + (*result)->height_unit = zend_string_init((const char*) height_unit_position, + xmlStrlen(height_unit_position), false); + } + } + + xmlFree(width); + xmlFree(height); + break; + } + } + + xmlFreeTextReader(reader); + + return is_svg ? SUCCESS : FAILURE; +} + +zend_result php_libxml_svg_image_identify(php_stream *stream) +{ + return php_libxml_svg_image_handle(stream, NULL); +} + +struct php_gfxinfo *php_libxml_svg_image_get_info(php_stream *stream) +{ + struct php_gfxinfo *result = NULL; + zend_result status = php_libxml_svg_image_handle(stream, &result); + ZEND_ASSERT((status == SUCCESS) == (result != NULL)); + return result; +} + +static const struct php_image_handler svg_image_handler = { + "image/svg+xml", + ".svg", + PHP_IMAGE_CONST_NAME("SVG"), + php_libxml_svg_image_identify, + php_libxml_svg_image_get_info, +}; + +void php_libxml_register_image_svg_handler(void) +{ + svg_image_type_id = php_image_register_handler(&svg_image_handler); +} + +zend_result php_libxml_unregister_image_svg_handler(void) +{ + return php_image_unregister_handler(svg_image_type_id); +} + +#endif diff --git a/ext/standard/php_smart_string.h b/ext/libxml/image_svg.h similarity index 77% rename from ext/standard/php_smart_string.h rename to ext/libxml/image_svg.h index 0013775d18f83..d023334af36b6 100644 --- a/ext/standard/php_smart_string.h +++ b/ext/libxml/image_svg.h @@ -10,10 +10,16 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Sascha Schumann | - | Xinchen Hui | + | Authors: Niels Dossche | +----------------------------------------------------------------------+ */ -/* Header moved to Zend. This file is retained for BC. */ -#include "zend_smart_string.h" +#ifndef LIBXML_IMAGE_SVG +#define LIBXML_IMAGE_SVG + +#include "zend.h" + +void php_libxml_register_image_svg_handler(void); +zend_result php_libxml_unregister_image_svg_handler(void); + +#endif diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 03a89c7aad51d..2e75d697296ab 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -43,6 +43,7 @@ #endif #include "php_libxml.h" +#include "image_svg.h" #define PHP_LIBXML_LOADED_VERSION ((char *)xmlParserVersion) @@ -84,8 +85,14 @@ static zend_long php_libxml_default_dump_doc_to_file(const char *filename, xmlDo /* }}} */ +static const zend_module_dep libxml_deps[] = { + ZEND_MOD_REQUIRED("standard") + ZEND_MOD_END +}; + zend_module_entry libxml_module_entry = { - STANDARD_MODULE_HEADER, + STANDARD_MODULE_HEADER_EX, NULL, + libxml_deps, "libxml", /* extension name */ ext_functions, /* extension function list */ PHP_MINIT(libxml), /* extension-wide startup function */ @@ -335,7 +342,26 @@ PHP_LIBXML_API void php_libxml_node_free_list(xmlNodePtr node) if (ptr->_private) { const php_libxml_node_object *obj = ptr->_private; if (!obj->document || obj->document->class_type < PHP_LIBXML_CLASS_MODERN) { - xmlReconciliateNs(curnode->doc, curnode); + if (LIBXML_VERSION < 21300 && UNEXPECTED(curnode->doc == NULL)) { + /* xmlReconciliateNs() in these versions just uses the document for xmlNewReconciledNs(), + * which can create an oldNs xml namespace declaration via xmlSearchNs() -> xmlTreeEnsureXMLDecl(). */ + xmlDoc dummy; + memset(&dummy, 0, sizeof(dummy)); + dummy.type = XML_DOCUMENT_NODE; + curnode->doc = &dummy; + xmlReconciliateNs(curnode->doc, curnode); + curnode->doc = NULL; + + /* Append oldNs to current node's nsDef, which can be at most one node. */ + if (dummy.oldNs) { + ZEND_ASSERT(dummy.oldNs->next == NULL); + xmlNsPtr old = curnode->nsDef; + curnode->nsDef = dummy.oldNs; + dummy.oldNs->next = old; + } + } else { + xmlReconciliateNs(curnode->doc, curnode); + } } } } @@ -969,6 +995,8 @@ static PHP_MINIT_FUNCTION(libxml) xmlOutputBufferCreateFilenameDefault(php_libxml_output_buffer_create_filename); } + php_libxml_register_image_svg_handler(); + return SUCCESS; } @@ -1010,7 +1038,7 @@ static PHP_MSHUTDOWN_FUNCTION(libxml) } php_libxml_shutdown(); - return SUCCESS; + return php_libxml_unregister_image_svg_handler(); } static zend_result php_libxml_post_deactivate(void) diff --git a/ext/libxml/libxml_arginfo.h b/ext/libxml/libxml_arginfo.h index b2eac9399df5c..1741b7fa98604 100644 --- a/ext/libxml/libxml_arginfo.h +++ b/ext/libxml/libxml_arginfo.h @@ -88,15 +88,10 @@ static void register_libxml_symbols(int module_number) zend_attribute *attribute_Deprecated_func_libxml_disable_entity_loader_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "libxml_disable_entity_loader", sizeof("libxml_disable_entity_loader") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_libxml_disable_entity_loader_0_arg0; - zend_string *attribute_Deprecated_func_libxml_disable_entity_loader_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_libxml_disable_entity_loader_0_arg0, attribute_Deprecated_func_libxml_disable_entity_loader_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_libxml_disable_entity_loader_0->args[0].value, &attribute_Deprecated_func_libxml_disable_entity_loader_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_libxml_disable_entity_loader_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_libxml_disable_entity_loader_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_libxml_disable_entity_loader_0_arg1; zend_string *attribute_Deprecated_func_libxml_disable_entity_loader_0_arg1_str = zend_string_init("as external entity loading is disabled by default", strlen("as external entity loading is disabled by default"), 1); - ZVAL_STR(&attribute_Deprecated_func_libxml_disable_entity_loader_0_arg1, attribute_Deprecated_func_libxml_disable_entity_loader_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_libxml_disable_entity_loader_0->args[1].value, &attribute_Deprecated_func_libxml_disable_entity_loader_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_libxml_disable_entity_loader_0->args[1].value, attribute_Deprecated_func_libxml_disable_entity_loader_0_arg1_str); attribute_Deprecated_func_libxml_disable_entity_loader_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } diff --git a/ext/libxml/tests/image/getimagesize.phpt b/ext/libxml/tests/image/getimagesize.phpt new file mode 100644 index 0000000000000..22c099395c3dd --- /dev/null +++ b/ext/libxml/tests/image/getimagesize.phpt @@ -0,0 +1,98 @@ +--TEST-- +getimagesize() with svg input +--EXTENSIONS-- +libxml +--FILE-- +", + "svg width=\"1\" height=\"1\"", + << + + +XML, + "", + "", + "", + "", + "", + "", + "", + "", +]; + +foreach ($inputs as $input) { + var_dump(getimagesizefromstring($input)); +} + +?> +--EXPECTF-- +bool(false) +bool(false) +array(6) { + [0]=> + int(4) + [1]=> + int(8) + [2]=> + int(%d) + ["mime"]=> + string(13) "image/svg+xml" + ["width_unit"]=> + string(2) "cm" + ["height_unit"]=> + string(2) "cm" +} +array(7) { + [0]=> + int(1) + [1]=> + int(1) + [2]=> + int(%d) + [3]=> + string(20) "width="1" height="1"" + ["mime"]=> + string(13) "image/svg+xml" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" +} +array(7) { + [0]=> + int(1) + [1]=> + int(1) + [2]=> + int(%d) + [3]=> + string(20) "width="1" height="1"" + ["mime"]=> + string(13) "image/svg+xml" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" +} +array(6) { + [0]=> + int(1) + [1]=> + int(1) + [2]=> + int(%d) + ["mime"]=> + string(13) "image/svg+xml" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "mm" +} +bool(false) +bool(false) +bool(false) +bool(false) +bool(false) diff --git a/ext/libxml/tests/image/imagetype_svg.phpt b/ext/libxml/tests/image/imagetype_svg.phpt new file mode 100644 index 0000000000000..4115e6a1c8955 --- /dev/null +++ b/ext/libxml/tests/image/imagetype_svg.phpt @@ -0,0 +1,16 @@ +--TEST-- +imagetype API with svg extension +--EXTENSIONS-- +libxml +--FILE-- + IMAGETYPE_SVG); +var_dump(image_type_to_extension(IMAGETYPE_SVG)); +var_dump(image_type_to_mime_type(IMAGETYPE_SVG)); + +?> +--EXPECT-- +bool(true) +string(4) ".svg" +string(13) "image/svg+xml" diff --git a/ext/libxml/tests/libxml_entity_loading_disabled_by_default.phpt b/ext/libxml/tests/libxml_entity_loading_disabled_by_default.phpt index 7a77547461931..f1ab4fa890637 100644 --- a/ext/libxml/tests/libxml_entity_loading_disabled_by_default.phpt +++ b/ext/libxml/tests/libxml_entity_loading_disabled_by_default.phpt @@ -30,7 +30,6 @@ function parseXML2($xml) { function parseXML3($xml) { $p = xml_parser_create(); xml_parse_into_struct($p, $xml, $vals, $index); - xml_parser_free($p); return var_export($vals, true); } diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cjk.c b/ext/mbstring/libmbfl/filters/mbfilter_cjk.c index bc14fe48f2cd8..716fec0c054d9 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_cjk.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_cjk.c @@ -21,15 +21,15 @@ * This macro converts uppercase ASCII values to Regional Indicator codepoints */ #define NFLAGS(c) (0x1F1A5+((unsigned int)(c))) -static const char nflags_s[10][2] = {"CN", "DE", "ES", "FR", "GB", "IT", "JP", "KR", "RU", "US"}; +static const char nflags_s[10][2] ZEND_NONSTRING = {"CN", "DE", "ES", "FR", "GB", "IT", "JP", "KR", "RU", "US"}; static const int nflags_code_kddi[10] = { 0x2549, 0x2546, 0x24C0, 0x2545, 0x2548, 0x2547, 0x2750, 0x254A, 0x24C1, 0x27F7 }; static const int nflags_code_sb[10] = { 0x2B0A, 0x2B05, 0x2B08, 0x2B04, 0x2B07, 0x2B06, 0x2B02, 0x2B0B, 0x2B09, 0x2B03 }; #define EMIT_KEYPAD_EMOJI(c) do { *snd = (c); return 0x20E3; } while(0) #define EMIT_FLAG_EMOJI(country) do { *snd = NFLAGS((country)[0]); return NFLAGS((country)[1]); } while(0) -static const char nflags_kddi[6][2] = {"FR", "DE", "IT", "GB", "CN", "KR"}; -static const char nflags_sb[10][2] = {"JP", "US", "FR", "DE", "IT", "GB", "ES", "RU", "CN", "KR"}; +static const char nflags_kddi[6][2] ZEND_NONSTRING = {"FR", "DE", "IT", "GB", "CN", "KR"}; +static const char nflags_sb[10][2] ZEND_NONSTRING = {"JP", "US", "FR", "DE", "IT", "GB", "ES", "RU", "CN", "KR"}; /* number -> (ku*94)+ten value for telephone keypad character */ #define DOCOMO_KEYPAD(n) ((n) == 0 ? 0x296F : (0x2965 + (n))) diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c index 0786c8e7f314a..41ffb97e58f16 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c @@ -725,7 +725,7 @@ static int mbfl_filt_conv_wchar_utf8_mobile(int c, mbfl_convert_filter *filter) * This macro converts uppercase ASCII values to Regional Indicator codepoints */ #define NFLAGS(c) (0x1F1A5+(int)(c)) -static const char nflags_s[10][2] = {"CN","DE","ES","FR","GB","IT","JP","KR","RU","US"}; +static const char nflags_s[10][2] ZEND_NONSTRING = {"CN","DE","ES","FR","GB","IT","JP","KR","RU","US"}; static const int nflags_code_kddi[10] = { 0x2549, 0x2546, 0x24C0, 0x2545, 0x2548, 0x2547, 0x2750, 0x254A, 0x24C1, 0x27F7 }; static const int nflags_code_sb[10] = { 0x2B0A, 0x2B05, 0x2B08, 0x2B04, 0x2B07, 0x2B06, 0x2B02, 0x2B0B, 0x2B09, 0x2B03 }; diff --git a/ext/mbstring/libmbfl/mbfl/eaw_table.h b/ext/mbstring/libmbfl/mbfl/eaw_table.h index 0150306835ba1..7bdacccee29ef 100644 --- a/ext/mbstring/libmbfl/mbfl/eaw_table.h +++ b/ext/mbstring/libmbfl/mbfl/eaw_table.h @@ -80,10 +80,10 @@ static const struct { { 0xff01, 0xff60 }, { 0xffe0, 0xffe6 }, { 0x16fe0, 0x16fe4 }, - { 0x16ff0, 0x16ff1 }, - { 0x17000, 0x187f7 }, - { 0x18800, 0x18cd5 }, - { 0x18cff, 0x18d08 }, + { 0x16ff0, 0x16ff6 }, + { 0x17000, 0x18cd5 }, + { 0x18cff, 0x18d1e }, + { 0x18d80, 0x18df2 }, { 0x1aff0, 0x1aff3 }, { 0x1aff5, 0x1affb }, { 0x1affd, 0x1affe }, @@ -125,7 +125,7 @@ static const struct { { 0x1f680, 0x1f6c5 }, { 0x1f6cc, 0x1f6cc }, { 0x1f6d0, 0x1f6d2 }, - { 0x1f6d5, 0x1f6d7 }, + { 0x1f6d5, 0x1f6d8 }, { 0x1f6dc, 0x1f6df }, { 0x1f6eb, 0x1f6ec }, { 0x1f6f4, 0x1f6fc }, @@ -135,11 +135,12 @@ static const struct { { 0x1f93c, 0x1f945 }, { 0x1f947, 0x1f9ff }, { 0x1fa70, 0x1fa7c }, - { 0x1fa80, 0x1fa89 }, - { 0x1fa8f, 0x1fac6 }, - { 0x1face, 0x1fadc }, - { 0x1fadf, 0x1fae9 }, - { 0x1faf0, 0x1faf8 }, + { 0x1fa80, 0x1fa8a }, + { 0x1fa8e, 0x1fac6 }, + { 0x1fac8, 0x1fac8 }, + { 0x1facd, 0x1fadc }, + { 0x1fadf, 0x1faea }, + { 0x1faef, 0x1faf8 }, { 0x20000, 0x2fffd }, { 0x30000, 0x3fffd }, }; diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 88f9b706ed243..4044f4de9ff57 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -1160,8 +1160,8 @@ PHP_RSHUTDOWN_FUNCTION(mbstring) MBSTRG(outconv_state) = 0; if (MBSTRG(all_encodings_list)) { - GC_DELREF(MBSTRG(all_encodings_list)); - zend_array_destroy(MBSTRG(all_encodings_list)); + /* must be *array* release to remove from GC root buffer and free the hashtable itself */ + zend_array_release(MBSTRG(all_encodings_list)); MBSTRG(all_encodings_list) = NULL; } @@ -1584,10 +1584,22 @@ PHP_FUNCTION(mb_output_handler) if (SG(sapi_headers).send_default_content_type || free_mimetype) { const char *charset = encoding->mime_name; if (charset) { - char *p; - size_t len = spprintf(&p, 0, "Content-Type: %s; charset=%s", mimetype, charset); - if (sapi_add_header(p, len, 0) != FAILURE) { - SG(sapi_headers).send_default_content_type = 0; + /* Don't try to add a header if we are in an output handler; + * we aren't supposed to directly access the output globals + * from outside of main/output.c, so just try to get the flags + * for the currently running handler, will only succeed if + * there is a handler running. */ + int unused; + bool in_handler = php_output_handler_hook( + PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, + &unused + ) == SUCCESS; + if (!in_handler) { + char *p; + size_t len = spprintf(&p, 0, "Content-Type: %s; charset=%s", mimetype, charset); + if (sapi_add_header(p, len, 0) != FAILURE) { + SG(sapi_headers).send_default_content_type = 0; + } } } @@ -4494,7 +4506,7 @@ PHP_FUNCTION(mb_send_mail) ZEND_PARSE_PARAMETERS_END(); if (str_headers) { - if (strlen(ZSTR_VAL(str_headers)) != ZSTR_LEN(str_headers)) { + if (UNEXPECTED(zend_str_has_nul_byte(str_headers))) { zend_argument_value_error(4, "must not contain any null bytes"); RETURN_THROWS(); } diff --git a/ext/mbstring/tests/bug54494.phpt b/ext/mbstring/tests/bug54494.phpt index 29a4b2fb59925..c32a9ad6df111 100644 --- a/ext/mbstring/tests/bug54494.phpt +++ b/ext/mbstring/tests/bug54494.phpt @@ -2,12 +2,11 @@ Bug #54494: mb_substr() mishandles UTF-32LE and UCS-2LE --EXTENSIONS-- mbstring +--INI-- +internal_encoding=UTF-8 --FILE-- 0x84) && (ord($gb) < 0x90 || ord($gb) > 0xE3)) || + return ((ord($gb[0]) < 0x81 || ord($gb[0]) > 0x84) && (ord($gb[0]) < 0x90 || ord($gb[0]) > 0xE3)) || (strlen($gb) > 1 && (ord($gb[1]) < 0x30 || ord($gb[1]) > 0x39)); } diff --git a/ext/mbstring/tests/gb18030_encoding.phpt b/ext/mbstring/tests/gb18030_encoding.phpt index 52cb7ae54482f..6c51fe35f204f 100644 --- a/ext/mbstring/tests/gb18030_encoding.phpt +++ b/ext/mbstring/tests/gb18030_encoding.phpt @@ -240,7 +240,7 @@ $gb18030_BMP_Mappings = [ findInvalidChars($toUnicode, $invalid, $truncated); function notFourByteCode($gb) { - return ((ord($gb) < 0x81 || ord($gb) > 0x84) && (ord($gb) < 0x90 || ord($gb) > 0xE3)) || + return ((ord($gb[0]) < 0x81 || ord($gb[0]) > 0x84) && (ord($gb[0]) < 0x90 || ord($gb[0]) > 0xE3)) || (strlen($gb) > 1 && (ord($gb[1]) < 0x30 || ord($gb[1]) > 0x39)); } diff --git a/ext/mbstring/tests/gh19397.phpt b/ext/mbstring/tests/gh19397.phpt new file mode 100644 index 0000000000000..e6e07b161c089 --- /dev/null +++ b/ext/mbstring/tests/gh19397.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-19397 (mb_list_encodings() can cause crashes on shutdown) +--EXTENSIONS-- +mbstring +--FILE-- + 0); +?> +--EXPECT-- +bool(true) diff --git a/ext/mbstring/tests/gh7902.phpt b/ext/mbstring/tests/gh7902.phpt index 7182731005ff6..e56c1792e1728 100644 --- a/ext/mbstring/tests/gh7902.phpt +++ b/ext/mbstring/tests/gh7902.phpt @@ -8,9 +8,9 @@ if (str_contains(getcwd(), " ")) die("skip sendmail_path ini with spaces"); ?> --INI-- sendmail_path={MAIL:{PWD}/gh7902.eml} +internal_encoding=UTF-8 --FILE-- $value) { echo "--$key--\n"; try { diff --git a/ext/mbstring/tests/mb_substr_basic.phpt b/ext/mbstring/tests/mb_substr_basic.phpt index 31de868fb93cf..acce6f5140d63 100644 --- a/ext/mbstring/tests/mb_substr_basic.phpt +++ b/ext/mbstring/tests/mb_substr_basic.phpt @@ -1,15 +1,11 @@ --TEST-- -Test mb_substr() function : basic functionality +Test mb_substr() function : basic functionality with ASCII characters and multibyte strings. --EXTENSIONS-- mbstring --INI-- internal_encoding=ISO-8859-1 --FILE-- args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_mysqli_execute_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mysqli_execute_0_arg1_str = zend_string_init("use mysqli_stmt_execute() instead", strlen("use mysqli_stmt_execute() instead"), 1); + ZVAL_STR(&attribute_Deprecated_func_mysqli_execute_0->args[1].value, attribute_Deprecated_func_mysqli_execute_0_arg1_str); + attribute_Deprecated_func_mysqli_execute_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + zend_attribute *attribute_Deprecated_func_mysqli_kill_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mysqli_kill", sizeof("mysqli_kill") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_mysqli_kill_0_arg0; - zend_string *attribute_Deprecated_func_mysqli_kill_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_mysqli_kill_0_arg0, attribute_Deprecated_func_mysqli_kill_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mysqli_kill_0->args[0].value, &attribute_Deprecated_func_mysqli_kill_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mysqli_kill_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_mysqli_kill_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_mysqli_kill_0_arg1; zend_string *attribute_Deprecated_func_mysqli_kill_0_arg1_str = zend_string_init("use KILL CONNECTION/QUERY SQL statement instead", strlen("use KILL CONNECTION/QUERY SQL statement instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_mysqli_kill_0_arg1, attribute_Deprecated_func_mysqli_kill_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mysqli_kill_0->args[1].value, &attribute_Deprecated_func_mysqli_kill_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_mysqli_kill_0->args[1].value, attribute_Deprecated_func_mysqli_kill_0_arg1_str); attribute_Deprecated_func_mysqli_kill_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_mysqli_ping_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mysqli_ping", sizeof("mysqli_ping") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_mysqli_ping_0_arg0; - zend_string *attribute_Deprecated_func_mysqli_ping_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_mysqli_ping_0_arg0, attribute_Deprecated_func_mysqli_ping_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mysqli_ping_0->args[0].value, &attribute_Deprecated_func_mysqli_ping_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mysqli_ping_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_mysqli_ping_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_mysqli_ping_0_arg1; zend_string *attribute_Deprecated_func_mysqli_ping_0_arg1_str = zend_string_init("because the reconnect feature has been removed in PHP 8.2 and this function is now redundant", strlen("because the reconnect feature has been removed in PHP 8.2 and this function is now redundant"), 1); - ZVAL_STR(&attribute_Deprecated_func_mysqli_ping_0_arg1, attribute_Deprecated_func_mysqli_ping_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mysqli_ping_0->args[1].value, &attribute_Deprecated_func_mysqli_ping_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_mysqli_ping_0->args[1].value, attribute_Deprecated_func_mysqli_ping_0_arg1_str); attribute_Deprecated_func_mysqli_ping_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "mysqli_real_connect", sizeof("mysqli_real_connect") - 1), 3, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_attribute *attribute_Deprecated_func_mysqli_refresh_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mysqli_refresh", sizeof("mysqli_refresh") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_mysqli_refresh_0_arg0; - zend_string *attribute_Deprecated_func_mysqli_refresh_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_mysqli_refresh_0_arg0, attribute_Deprecated_func_mysqli_refresh_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mysqli_refresh_0->args[0].value, &attribute_Deprecated_func_mysqli_refresh_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_mysqli_refresh_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_mysqli_refresh_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_mysqli_refresh_0_arg1; zend_string *attribute_Deprecated_func_mysqli_refresh_0_arg1_str = zend_string_init("use FLUSH SQL statement instead", strlen("use FLUSH SQL statement instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_mysqli_refresh_0_arg1, attribute_Deprecated_func_mysqli_refresh_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_mysqli_refresh_0->args[1].value, &attribute_Deprecated_func_mysqli_refresh_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_mysqli_refresh_0->args[1].value, attribute_Deprecated_func_mysqli_refresh_0_arg1_str); attribute_Deprecated_func_mysqli_refresh_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0 = zend_add_global_constant_attribute(const_MYSQLI_STORE_RESULT_COPY_DATA, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0_arg1_str = zend_string_init("as the mysqli_store_result() parameter is unused since 8.1", strlen("as the mysqli_store_result() parameter is unused since 8.1"), 1); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0->args[1].value, attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0_arg1_str); + attribute_Deprecated_const_MYSQLI_STORE_RESULT_COPY_DATA_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_NO_DATA_0 = zend_add_global_constant_attribute(const_MYSQLI_NO_DATA, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_NO_DATA_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_MYSQLI_NO_DATA_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str = zend_string_init("as it was unused", strlen("as it was unused"), 1); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_NO_DATA_0->args[1].value, attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str); + attribute_Deprecated_const_MYSQLI_NO_DATA_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0 = zend_add_global_constant_attribute(const_MYSQLI_DATA_TRUNCATED, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0->args[1].value, attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str); + attribute_Deprecated_const_MYSQLI_DATA_TRUNCATED_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0 = zend_add_global_constant_attribute(const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0->args[1].value, attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str); + attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0 = zend_add_global_constant_attribute(const_MYSQLI_SERVER_QUERY_NO_INDEX_USED, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0->args[1].value, attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str); + attribute_Deprecated_const_MYSQLI_SERVER_QUERY_NO_INDEX_USED_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0 = zend_add_global_constant_attribute(const_MYSQLI_SERVER_QUERY_WAS_SLOW, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0->args[1].value, attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str); + attribute_Deprecated_const_MYSQLI_SERVER_QUERY_WAS_SLOW_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0 = zend_add_global_constant_attribute(const_MYSQLI_SERVER_PS_OUT_PARAMS, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0->args[1].value, attribute_Deprecated_const_MYSQLI_NO_DATA_0_arg1_str); + attribute_Deprecated_const_MYSQLI_SERVER_PS_OUT_PARAMS_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_GRANT, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str = zend_string_init("as mysqli_refresh() is deprecated", strlen("as mysqli_refresh() is deprecated"), 1); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_LOG, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_LOG_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_TABLES, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_TABLES_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_HOSTS, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_HOSTS_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_STATUS, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_STATUS_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_THREADS, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_THREADS_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_REPLICA, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_REPLICA_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_SLAVE, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_SLAVE_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_MASTER, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_MASTER_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0 = zend_add_global_constant_attribute(const_MYSQLI_REFRESH_BACKUP_LOG, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0->args[1].value, attribute_Deprecated_const_MYSQLI_REFRESH_GRANT_0_arg1_str); + attribute_Deprecated_const_MYSQLI_REFRESH_BACKUP_LOG_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MYSQLI_IS_MARIADB_0 = zend_add_global_constant_attribute(const_MYSQLI_IS_MARIADB, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_IS_MARIADB_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_2)); + attribute_Deprecated_const_MYSQLI_IS_MARIADB_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_MYSQLI_IS_MARIADB_0_arg1_str = zend_string_init("as it is always false", strlen("as it is always false"), 1); + ZVAL_STR(&attribute_Deprecated_const_MYSQLI_IS_MARIADB_0->args[1].value, attribute_Deprecated_const_MYSQLI_IS_MARIADB_0_arg1_str); + attribute_Deprecated_const_MYSQLI_IS_MARIADB_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_mysqli_driver(void) @@ -1346,65 +1450,40 @@ static zend_class_entry *register_class_mysqli(void) zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "connect", sizeof("connect") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_attribute *attribute_Deprecated_func_get_client_info_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "get_client_info", sizeof("get_client_info") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_get_client_info_0_arg0; - zend_string *attribute_Deprecated_func_get_client_info_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_get_client_info_0_arg0, attribute_Deprecated_func_get_client_info_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_get_client_info_0->args[0].value, &attribute_Deprecated_func_get_client_info_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_get_client_info_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_get_client_info_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_get_client_info_0_arg1; zend_string *attribute_Deprecated_func_get_client_info_0_arg1_str = zend_string_init("use mysqli_get_client_info() instead", strlen("use mysqli_get_client_info() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_get_client_info_0_arg1, attribute_Deprecated_func_get_client_info_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_get_client_info_0->args[1].value, &attribute_Deprecated_func_get_client_info_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_get_client_info_0->args[1].value, attribute_Deprecated_func_get_client_info_0_arg1_str); attribute_Deprecated_func_get_client_info_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_init_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "init", sizeof("init") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_init_0_arg0; - zend_string *attribute_Deprecated_func_init_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_init_0_arg0, attribute_Deprecated_func_init_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_init_0->args[0].value, &attribute_Deprecated_func_init_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_init_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_init_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_init_0_arg1; zend_string *attribute_Deprecated_func_init_0_arg1_str = zend_string_init("replace calls to parent::init() with parent::__construct()", strlen("replace calls to parent::init() with parent::__construct()"), 1); - ZVAL_STR(&attribute_Deprecated_func_init_0_arg1, attribute_Deprecated_func_init_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_init_0->args[1].value, &attribute_Deprecated_func_init_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_init_0->args[1].value, attribute_Deprecated_func_init_0_arg1_str); attribute_Deprecated_func_init_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_kill_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "kill", sizeof("kill") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_kill_0_arg0; - zend_string *attribute_Deprecated_func_kill_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_kill_0_arg0, attribute_Deprecated_func_kill_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_kill_0->args[0].value, &attribute_Deprecated_func_kill_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_kill_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_kill_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_kill_0_arg1; zend_string *attribute_Deprecated_func_kill_0_arg1_str = zend_string_init("use KILL CONNECTION/QUERY SQL statement instead", strlen("use KILL CONNECTION/QUERY SQL statement instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_kill_0_arg1, attribute_Deprecated_func_kill_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_kill_0->args[1].value, &attribute_Deprecated_func_kill_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_kill_0->args[1].value, attribute_Deprecated_func_kill_0_arg1_str); attribute_Deprecated_func_kill_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_ping_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "ping", sizeof("ping") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_ping_0_arg0; - zend_string *attribute_Deprecated_func_ping_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_ping_0_arg0, attribute_Deprecated_func_ping_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_ping_0->args[0].value, &attribute_Deprecated_func_ping_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_ping_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_ping_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_ping_0_arg1; zend_string *attribute_Deprecated_func_ping_0_arg1_str = zend_string_init("because the reconnect feature has been removed in PHP 8.2 and this method is now redundant", strlen("because the reconnect feature has been removed in PHP 8.2 and this method is now redundant"), 1); - ZVAL_STR(&attribute_Deprecated_func_ping_0_arg1, attribute_Deprecated_func_ping_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_ping_0->args[1].value, &attribute_Deprecated_func_ping_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_ping_0->args[1].value, attribute_Deprecated_func_ping_0_arg1_str); attribute_Deprecated_func_ping_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "real_connect", sizeof("real_connect") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_attribute *attribute_Deprecated_func_refresh_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "refresh", sizeof("refresh") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_refresh_0_arg0; - zend_string *attribute_Deprecated_func_refresh_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_refresh_0_arg0, attribute_Deprecated_func_refresh_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_refresh_0->args[0].value, &attribute_Deprecated_func_refresh_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_refresh_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_refresh_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_refresh_0_arg1; zend_string *attribute_Deprecated_func_refresh_0_arg1_str = zend_string_init("use FLUSH SQL statement instead", strlen("use FLUSH SQL statement instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_refresh_0_arg1, attribute_Deprecated_func_refresh_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_refresh_0->args[1].value, &attribute_Deprecated_func_refresh_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_refresh_0->args[1].value, attribute_Deprecated_func_refresh_0_arg1_str); attribute_Deprecated_func_refresh_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); return class_entry; diff --git a/ext/mysqli/mysqli_report.c b/ext/mysqli/mysqli_report.c index 68a7a57584750..06611310b0b0c 100644 --- a/ext/mysqli/mysqli_report.c +++ b/ext/mysqli/mysqli_report.c @@ -48,12 +48,12 @@ void php_mysqli_report_error(const char *sqlstate, int errorno, const char *erro /* {{{ void php_mysqli_report_index() */ void php_mysqli_report_index(const char *query, unsigned int status) { - char index[15]; + const char *index; if (status & SERVER_QUERY_NO_GOOD_INDEX_USED) { - strcpy(index, "Bad index"); + index = "Bad index"; } else if (status & SERVER_QUERY_NO_INDEX_USED) { - strcpy(index, "No index"); + index = "No index"; } else { return; } diff --git a/ext/mysqli/tests/bug77956.phpt b/ext/mysqli/tests/bug77956.phpt index 28cf694a606a8..d5409f9527511 100644 --- a/ext/mysqli/tests/bug77956.phpt +++ b/ext/mysqli/tests/bug77956.phpt @@ -57,5 +57,5 @@ $link->close(); unlink('bug77956.data'); ?> --EXPECT-- -[006] [2000] LOAD DATA LOCAL INFILE is forbidden, check related settings like mysqli.allow_local_infile|mysqli.local_infile_directory or PDO::MYSQL_ATTR_LOCAL_INFILE|PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY +[006] [2000] LOAD DATA LOCAL INFILE is forbidden, check related settings like mysqli.allow_local_infile|mysqli.local_infile_directory or Pdo\Mysql::ATTR_LOCAL_INFILE|Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY done diff --git a/ext/mysqli/tests/deprecated_constants.phpt b/ext/mysqli/tests/deprecated_constants.phpt index 9c8e06e50fe1c..753863a3bf131 100644 --- a/ext/mysqli/tests/deprecated_constants.phpt +++ b/ext/mysqli/tests/deprecated_constants.phpt @@ -16,22 +16,22 @@ echo constant('MYSQLI_IS_MARIADB')."\n"; ?> --EXPECTF-- -Deprecated: Constant MYSQLI_NO_DATA is deprecated in %s +Deprecated: Constant MYSQLI_NO_DATA is deprecated since 8.1, as it was unused in %s %i -Deprecated: Constant MYSQLI_DATA_TRUNCATED is deprecated in %s +Deprecated: Constant MYSQLI_DATA_TRUNCATED is deprecated since 8.1, as it was unused in %s %i -Deprecated: Constant MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED is deprecated in %s +Deprecated: Constant MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED is deprecated since 8.1, as it was unused in %s %i -Deprecated: Constant MYSQLI_SERVER_QUERY_NO_INDEX_USED is deprecated in %s +Deprecated: Constant MYSQLI_SERVER_QUERY_NO_INDEX_USED is deprecated since 8.1, as it was unused in %s %i -Deprecated: Constant MYSQLI_SERVER_QUERY_WAS_SLOW is deprecated in %s +Deprecated: Constant MYSQLI_SERVER_QUERY_WAS_SLOW is deprecated since 8.1, as it was unused in %s %i -Deprecated: Constant MYSQLI_SERVER_PS_OUT_PARAMS is deprecated in %s +Deprecated: Constant MYSQLI_SERVER_PS_OUT_PARAMS is deprecated since 8.1, as it was unused in %s %i -Deprecated: Constant MYSQLI_IS_MARIADB is deprecated in %s +Deprecated: Constant MYSQLI_IS_MARIADB is deprecated since 8.2, as it is always false in %s diff --git a/ext/mysqlnd/mysqlnd_loaddata.c b/ext/mysqlnd/mysqlnd_loaddata.c index ba2dabf95a2c5..a1e04de270085 100644 --- a/ext/mysqlnd/mysqlnd_loaddata.c +++ b/ext/mysqlnd/mysqlnd_loaddata.c @@ -167,7 +167,7 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * const filenam SET_CLIENT_ERROR(conn->error_info, CR_LOAD_DATA_LOCAL_INFILE_REJECTED, UNKNOWN_SQLSTATE, "LOAD DATA LOCAL INFILE is forbidden, check related settings like " "mysqli.allow_local_infile|mysqli.local_infile_directory or " - "PDO::MYSQL_ATTR_LOCAL_INFILE|PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY"); + "Pdo\\Mysql::ATTR_LOCAL_INFILE|Pdo\\Mysql::ATTR_LOCAL_INFILE_DIRECTORY"); prerequisities_ok = FALSE; } diff --git a/ext/mysqlnd/mysqlnd_portability.h b/ext/mysqlnd/mysqlnd_portability.h index 11ebf4d1bf8ae..20dfe3429edf3 100644 --- a/ext/mysqlnd/mysqlnd_portability.h +++ b/ext/mysqlnd/mysqlnd_portability.h @@ -284,15 +284,8 @@ typedef union { register) variable, M is a pointer to byte */ #ifndef float8get - -#ifdef WORDS_BIGENDIAN -#define float8get(V,M) memcpy((char*) &(V),(char*) (M), sizeof(double)) -#define float8store(T,V) memcpy((char*) (T),(char*) &(V), sizeof(double)) -#else -#define float8get(V,M) memcpy((char*) &(V),(char*) (M),sizeof(double)) -#define float8store(T,V) memcpy((char*) (T),(char*) &(V),sizeof(double)) -#endif /* WORDS_BIGENDIAN */ - -#endif /* float8get */ +# define float8get(V,M) memcpy((char*) &(V),(char*) (M),sizeof(double)) +# define float8store(T,V) memcpy((char*) (T),(char*) &(V),sizeof(double)) +#endif #endif /* MYSQLND_PORTABILITY_H */ diff --git a/ext/mysqlnd/mysqlnd_vio.c b/ext/mysqlnd/mysqlnd_vio.c index 67210f083a967..3a3f7b207214a 100644 --- a/ext/mysqlnd/mysqlnd_vio.c +++ b/ext/mysqlnd/mysqlnd_vio.c @@ -26,7 +26,7 @@ #ifndef PHP_WIN32 #include #else -#include +#include #endif diff --git a/ext/odbc/config.m4 b/ext/odbc/config.m4 index 9baa8dbd8e646..645a4d52902e8 100644 --- a/ext/odbc/config.m4 +++ b/ext/odbc/config.m4 @@ -7,179 +7,10 @@ AC_DEFUN([PHP_ODBC_CHECK_HEADER], [AS_IF([test ! -f "$ODBC_INCDIR/$1"], [AC_MSG_ERROR([ODBC header file '$ODBC_INCDIR/$1' not found!])])]) -dnl -dnl PHP_ODBC_FIND_SOLID_LIBS(libdir) -dnl -dnl Figure out which library file to link with for the Solid support. -dnl -AC_DEFUN([PHP_ODBC_FIND_SOLID_LIBS],[ - AC_MSG_CHECKING([Solid library file]) - ac_solid_uname_r=$(uname -r 2>/dev/null) - ac_solid_uname_s=$(uname -s 2>/dev/null) - case $ac_solid_uname_s in - AIX) ac_solid_os=a3x;; # a4x for AIX4/ Solid 2.3/3.0 only - HP-UX) ac_solid_os=h9x;; # h1x for hpux11, h0x for hpux10 - Linux) - if ldd -v /bin/sh | grep GLIBC > /dev/null; then - ac_solid_os=l2x - else - ac_solid_os=lux - fi - AC_DEFINE([SS_LINUX], [1], - [Define to 1 to be able to use the obsolete header file on - some Linux systems.]) - ;; - SunOS) - ac_solid_os=ssx;; # should we deal with SunOS 4? - FreeBSD) - if test $(expr $ac_solid_uname_r : '\(.\)') -gt "2"; then - ac_solid_os=fex - else - ac_solid_os=fbx - fi - AC_DEFINE([SS_FBX], [1], - [Define to 1 to be able to use the wchar defs in the obsolete - header file on some FreeBSD systems.]) - ;; - esac - - if test -f $1/soc${ac_solid_os}35.a; then - ac_solid_version=35 - ac_solid_prefix=soc - elif test -f $1/scl${ac_solid_os}30.a; then - ac_solid_version=30 - ac_solid_prefix=scl - elif test -f $1/scl${ac_solid_os}23.a; then - ac_solid_version=23 - ac_solid_prefix=scl - fi - -dnl Check for the library files, and setup the ODBC_LIBS path. -if test ! -f $1/lib${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.so && \ - test ! -f $1/lib${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.a; then - dnl we have an error and should bail out, as we can't find the libs! - echo "" - echo "*********************************************************************" - echo "* Unable to locate $1/lib${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.so or $1/lib${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.a" - echo "* Please correct this by creating the following links and reconfiguring:" - echo "* $1/lib${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.a -> $1/lib${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.a" - echo "* $1/${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.so -> $1/lib${ac_solid_prefix}${ac_solid_os}${ac_solid_version}.so" - echo "*********************************************************************" -else - ODBC_LFLAGS=-L$1 - ODBC_LIBS=-l${ac_solid_prefix}${ac_solid_os}${ac_solid_version} -fi - - AC_MSG_RESULT([$(echo $ODBC_LIBS | $SED -e 's!.*/!!')]) -]) - -dnl -dnl PHP_ODBC_FIND_EMPRESS_LIBS(libdir) -dnl -dnl Figure out which library file to link with for the Empress support. -dnl -AC_DEFUN([PHP_ODBC_FIND_EMPRESS_LIBS],[ - AC_MSG_CHECKING([Empress library file]) - ODBC_LIBS=$(echo $1/libempodbccl.so | cut -d' ' -f1) - if test ! -f $ODBC_LIBS; then - ODBC_LIBS=$(echo $1/libempodbccl.so | cut -d' ' -f1) - fi - AC_MSG_RESULT([$(echo $ODBC_LIBS | $SED -e 's!.*/!!')]) -]) - -dnl -dnl PHP_ODBC_FIND_EMPRESS_BCS_LIBS(libdir) -dnl -dnl Figure out which library file to link with for the Empress local access -dnl support. -dnl -AC_DEFUN([PHP_ODBC_FIND_EMPRESS_BCS_LIBS],[ - AC_MSG_CHECKING([Empress local access library file]) - ODBCBCS_LIBS=$(echo $1/libempodbcbcs.a | cut -d' ' -f1) - if test ! -f $ODBCBCS_LIBS; then - ODBCBCS_LIBS=$(echo $1/libempodbcbcs.a | cut -d' ' -f1) - fi - AC_MSG_RESULT([$(echo $ODBCBCS_LIBS | $SED -e 's!.*/!!')]) -]) - dnl dnl configure options dnl -PHP_ARG_WITH([odbcver],, - [AS_HELP_STRING([[--with-odbcver[=HEX]]], - [Force support for the passed ODBC version. A hex number is expected, - default 0x0350. Use the special value of 0 to prevent an explicit ODBCVER to - be defined.])], - [0x0350]) - -AS_VAR_IF([ODBC_TYPE],, [ -PHP_ARG_WITH([adabas], - [for Adabas support], - [AS_HELP_STRING([[--with-adabas[=DIR]]], - [Include Adabas D support [/usr/local]])]) - - AS_VAR_IF([PHP_ADABAS], [no], [], [ - AS_VAR_IF([PHP_ADABAS], [yes], [PHP_ADABAS=/usr/local]) - PHP_ADD_INCLUDE([$PHP_ADABAS/incl]) - PHP_ADD_LIBPATH([$PHP_ADABAS/$PHP_LIBDIR]) - ODBC_OBJS="$PHP_ADABAS/$PHP_LIBDIR/odbclib.a" - ODBC_LIB="$abs_builddir/ext/odbc/libodbc_adabas.a" - $srcdir/build/shtool mkdir -f -p ext/odbc - rm -f "$ODBC_LIB" - cp "$ODBC_OBJS" "$ODBC_LIB" - PHP_ADD_LIBRARY([sqlptc]) - PHP_ADD_LIBRARY([sqlrte]) - PHP_ADD_LIBRARY_WITH_PATH([odbc_adabas], [$abs_builddir/ext/odbc]) - ODBC_TYPE=adabas - ODBC_INCDIR=$PHP_ADABAS/incl - PHP_ODBC_CHECK_HEADER([sqlext.h]) - AC_DEFINE([HAVE_ADABAS], [1], - [Define to 1 if the odbc extension uses the Adabas D.]) - ]) -]) - -AS_VAR_IF([ODBC_TYPE],, [ -PHP_ARG_WITH([sapdb], - [for SAP DB support], - [AS_HELP_STRING([[--with-sapdb[=DIR]]], - [Include SAP DB support [/usr/local]])]) - - AS_VAR_IF([PHP_SAPDB], [no], [], [ - AS_VAR_IF([PHP_SAPDB], [yes], [PHP_SAPDB=/usr/local]) - PHP_ADD_INCLUDE([$PHP_SAPDB/incl]) - PHP_ADD_LIBPATH([$PHP_SAPDB/$PHP_LIBDIR]) - PHP_ADD_LIBRARY([sqlod]) - ODBC_TYPE=sapdb - AC_DEFINE([HAVE_SAPDB], [1], - [Define to 1 if the odbc extension uses the SAP DB.]) - ]) -]) - -AS_VAR_IF([ODBC_TYPE],, [ -PHP_ARG_WITH([solid], - [for Solid support], - [AS_HELP_STRING([[--with-solid[=DIR]]], - [Include Solid support [/usr/local/solid]])]) - - AS_VAR_IF([PHP_SOLID], [no], [], [ - AS_VAR_IF([PHP_SOLID], [yes], [PHP_SOLID=/usr/local/solid]) - ODBC_INCDIR=$PHP_SOLID/include - ODBC_LIBDIR=$PHP_SOLID/$PHP_LIBDIR - ODBC_CFLAGS=-I$ODBC_INCDIR - ODBC_TYPE=solid - if test -f $ODBC_LIBDIR/soc*35.a; then - AC_DEFINE([HAVE_SOLID_35], [1], [Define to 1 if Solid DB 3.5 is used.]) - elif test -f $ODBC_LIBDIR/scl*30.a; then - AC_DEFINE([HAVE_SOLID_30], [1], [Define to 1 if Solid DB 3.0 is used.]) - elif test -f $ODBC_LIBDIR/scl*23.a; then - AC_DEFINE([HAVE_SOLID], [1], - [Define to 1 if the odbc extension uses the Solid DB.]) - fi - PHP_ODBC_FIND_SOLID_LIBS([$ODBC_LIBDIR]) - ]) -]) - AS_VAR_IF([ODBC_TYPE],, [ PHP_ARG_WITH([ibm-db2], [for IBM DB2 support], @@ -217,70 +48,6 @@ PHP configure: ]) ]) -AS_VAR_IF([ODBC_TYPE],, [ -PHP_ARG_WITH([empress], - [for Empress support], - [AS_HELP_STRING([[--with-empress[=DIR]]], - [Include Empress support $EMPRESSPATH (Empress Version >= 8.60 - required)])]) - - AS_VAR_IF([PHP_EMPRESS], [no], [], [ - AS_VAR_IF([PHP_EMPRESS], [yes], [ - ODBC_INCDIR=$EMPRESSPATH/include/odbc - ODBC_LIBDIR=$EMPRESSPATH/shlib - ], [ - ODBC_INCDIR=$PHP_EMPRESS/include/odbc - ODBC_LIBDIR=$PHP_EMPRESS/shlib - ]) - ODBC_CFLAGS=-I$ODBC_INCDIR - ODBC_LFLAGS=-L$ODBC_LIBDIR - ODBC_TYPE=empress - AC_DEFINE([HAVE_EMPRESS], [1], - [Define to 1 if the odbc extension uses the Empress.]) - PHP_ODBC_FIND_EMPRESS_LIBS([$ODBC_LIBDIR]) - ]) -]) - -AS_VAR_IF([ODBC_TYPE],, [ -PHP_ARG_WITH([empress-bcs], - [for Empress local access support], - [AS_HELP_STRING([[--with-empress-bcs[=DIR]]], - [Include Empress Local Access support $EMPRESSPATH (Empress Version >= - 8.60 required)])]) - - AS_VAR_IF([PHP_EMPRESS_BCS], [no], [], [ - AS_VAR_IF([PHP_EMPRESS_BCS], [yes], [ - ODBC_INCDIR=$EMPRESSPATH/include/odbc - ODBC_LIBDIR=$EMPRESSPATH/shlib - ], [ - ODBC_INCDIR=$PHP_EMPRESS_BCS/include/odbc - ODBC_LIBDIR=$PHP_EMPRESS_BCS/shlib - ]) - CC="empocc -bcs";export CC; - LD="empocc -bcs";export LD; - ODBC_CFLAGS=-I$ODBC_INCDIR - ODBC_LFLAGS=-L$ODBC_LIBDIR - LIST=$(empocc -listlines -bcs -o a a.c) - - NEWLIST= - for I in $LIST - do - case $I in - $EMPRESSPATH/odbccl/lib/* | \ - $EMPRESSPATH/rdbms/lib/* | \ - $EMPRESSPATH/common/lib/*) - NEWLIST="$NEWLIST $I" - ;; - esac - done - ODBC_LIBS="-lempphpbcs -lms -lmscfg -lbasic -lbasic_os -lnlscstab -lnlsmsgtab -lm -ldl -lcrypt" - ODBC_TYPE=empress-bcs - AC_DEFINE([HAVE_EMPRESS], [1], - [Define to 1 if the odbc extension uses the Empress.]) - PHP_ODBC_FIND_EMPRESS_BCS_LIBS([$ODBC_LIBDIR]) - ]) -]) - AS_VAR_IF([ODBC_TYPE],, [ PHP_ARG_WITH([custom-odbc], [for a custom ODBC support], @@ -320,25 +87,6 @@ PHP_ARG_WITH([iodbc], ]) ]) -AS_VAR_IF([ODBC_TYPE],, [ -PHP_ARG_WITH([esoob], - [for Easysoft ODBC-ODBC Bridge support], - [AS_HELP_STRING([[--with-esoob[=DIR]]], - [Include Easysoft OOB support [/usr/local/easysoft/oob/client]])]) - - AS_VAR_IF([PHP_ESOOB], [no], [], [ - AS_VAR_IF([PHP_ESOOB], [yes], [PHP_ESOOB=/usr/local/easysoft/oob/client]) - ODBC_INCDIR=$PHP_ESOOB/include - ODBC_LIBDIR=$PHP_ESOOB/$PHP_LIBDIR - ODBC_LFLAGS=-L$ODBC_LIBDIR - ODBC_CFLAGS=-I$ODBC_INCDIR - ODBC_LIBS=-lesoobclient - ODBC_TYPE=esoob - AC_DEFINE([HAVE_ESOOB], [1], - [Define to 1 if the odbc extension uses the Easysoft OOB.]) - ]) -]) - AS_VAR_IF([ODBC_TYPE],, [ PHP_ARG_WITH([unixODBC], [whether to build with unixODBC support], @@ -367,64 +115,10 @@ PHP_ARG_WITH([unixODBC], ]) ]) -AS_VAR_IF([ODBC_TYPE],, [ -PHP_ARG_WITH([dbmaker], - [for DBMaker support], - [AS_HELP_STRING([[--with-dbmaker[=DIR]]], - [Include DBMaker support])]) - - AS_VAR_IF([PHP_DBMAKER], [no], [], [ - AS_VAR_IF([PHP_DBMAKER], [yes], [ - dnl Find dbmaker home directory - DBMAKER_HOME=$(grep "^dbmaker:" /etc/passwd | $AWK -F: '{print $6}') - - dnl check DBMaker version (from 5.0 to 2.0) - DBMAKER_VERSION=5.0 - - while test ! -d $DBMAKER_HOME/$DBMAKER_VERSION && test "$DBMAKER_VERSION" != "2.9"; do - DM_VER=$(echo $DBMAKER_VERSION | $SED -e 's/\.//' | $AWK '{ print $1-1;}') - MAJOR_V=$(echo $DM_VER | $AWK '{ print $1/10; }' | $AWK -F. '{ print $1; }') - MINOR_V=$(echo $DM_VER | $AWK '{ print $1%10; }') - DBMAKER_VERSION=$MAJOR_V.$MINOR_V - done - - AS_VAR_IF([DBMAKER_VERSION], [2.9], - [PHP_DBMAKER=$DBMAKER_HOME], - [PHP_DBMAKER=$DBMAKER_HOME/$DBMAKER_VERSION]) - ]) - - ODBC_INCDIR=$PHP_DBMAKER/include - ODBC_LIBDIR=$PHP_DBMAKER/$PHP_LIBDIR - ODBC_CFLAGS=-I$ODBC_INCDIR - ODBC_LFLAGS=-L$ODBC_LIBDIR - ODBC_LIBS="-ldmapic -lc" - ODBC_TYPE=dbmaker - - AC_DEFINE([HAVE_DBMAKER], [1], - [Define to 1 if the odbc extension uses the DBMaker.]) - - AS_VAR_IF([ext_shared], [yes], [ODBC_LIBS="-ldmapic -lc -lm"], [ - PHP_ADD_LIBRARY_WITH_PATH([dmapic], [$ODBC_LIBDIR]) - PHP_ADD_INCLUDE([$ODBC_INCDIR]) - ]) - ]) -]) - -AH_TEMPLATE([ODBCVER], [The highest supported ODBC version.]) -AS_VAR_IF([PHP_ODBCVER], [no], - [AC_DEFINE([ODBCVER], [0x0350])], - [AS_VAR_IF([PHP_ODBCVER], [0],, - [AC_DEFINE_UNQUOTED([ODBCVER], [$PHP_ODBCVER])])]) dnl Extension setup if test -n "$ODBC_TYPE"; then - AS_VAR_IF([ODBC_TYPE], [dbmaker],, [ - PHP_EVAL_LIBLINE([$ODBC_LFLAGS $ODBC_LIBS], [ODBC_SHARED_LIBADD]) - AS_VAR_IF([ODBC_TYPE], [solid],, - [AC_DEFINE([HAVE_SQLDATASOURCES], [1], - [Define to 1 if ODBC library has 'SQLDataSources', as a function or - macro.])]) - ]) + PHP_EVAL_LIBLINE([$ODBC_LFLAGS $ODBC_LIBS], [ODBC_SHARED_LIBADD]) AC_DEFINE([HAVE_UODBC], [1], [Define to 1 if the PHP extension 'odbc' is available.]) diff --git a/ext/odbc/config.w32 b/ext/odbc/config.w32 index 1030db44465be..7afa9ce8b6490 100644 --- a/ext/odbc/config.w32 +++ b/ext/odbc/config.w32 @@ -1,7 +1,6 @@ // vim:ft=javascript ARG_ENABLE("odbc", "ODBC support", "no"); -ARG_WITH("odbcver", "Force support for the passed ODBC version. A hex number is expected, default 0x0350. Use the special value of 0 to prevent an explicit ODBCVER to be defined.", "0x0350"); if (PHP_ODBC == "yes") { if (CHECK_LIB("odbc32.lib", "odbc") && CHECK_LIB("odbccp32.lib", "odbc") @@ -9,12 +8,6 @@ if (PHP_ODBC == "yes") { && CHECK_HEADER_ADD_INCLUDE("sqlext.h", "CFLAGS_ODBC")) { EXTENSION("odbc", "php_odbc.c odbc_utils.c", PHP_ODBC_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); AC_DEFINE("HAVE_UODBC", 1, "Define to 1 if the PHP extension 'odbc' is available."); - AC_DEFINE("HAVE_SQLDATASOURCES", 1, "Define to 1 if ODBC library has 'SQLDataSources', as a function or macro."); - if ("no" == PHP_ODBCVER) { - AC_DEFINE("ODBCVER", "0x0350", "The highest supported ODBC version.", false); - } else if ("0" != PHP_ODBCVER) { - AC_DEFINE("ODBCVER", PHP_ODBCVER, "The highest supported ODBC version.", false); - } } else { WARNING("odbc support can't be enabled, libraries or header are missing (SDK)") PHP_ODBC = "no" diff --git a/ext/odbc/odbc.stub.php b/ext/odbc/odbc.stub.php index 8a54e913e88ed..f88a71154f8f0 100644 --- a/ext/odbc/odbc.stub.php +++ b/ext/odbc/odbc.stub.php @@ -233,8 +233,6 @@ class Result * @cvalue SQL_TIMESTAMP */ const SQL_TIMESTAMP = UNKNOWN; - -#if (defined(ODBCVER) && (ODBCVER >= 0x0300)) /** * @var int * @cvalue SQL_TYPE_DATE @@ -327,8 +325,6 @@ class Result */ const SQL_QUICK = UNKNOWN; -#endif - function odbc_close_all(): void {} function odbc_binmode(Odbc\Result $statement, int $mode): true {} @@ -341,20 +337,16 @@ function odbc_execute(Odbc\Result $statement, array $params = []): bool {} function odbc_cursor(Odbc\Result $statement): string|false {} -#ifdef HAVE_SQLDATASOURCES function odbc_data_source(Odbc\Connection $odbc, int $fetch_type): array|null|false {} -#endif function odbc_exec(Odbc\Connection $odbc, string $query): Odbc\Result|false {} /** @alias odbc_exec */ function odbc_do(Odbc\Connection $odbc, string $query): Odbc\Result|false {} -#ifdef PHP_ODBC_HAVE_FETCH_HASH function odbc_fetch_object(Odbc\Result $statement, ?int $row = null): stdClass|false {} function odbc_fetch_array(Odbc\Result $statement, ?int $row = null): array|false {} -#endif /** * @param array $array @@ -378,9 +370,7 @@ function odbc_close(Odbc\Connection $odbc): void {} function odbc_num_rows(Odbc\Result $statement): int {} -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) function odbc_next_result(Odbc\Result $statement): bool {} -#endif function odbc_num_fields(Odbc\Result $statement): int {} @@ -417,23 +407,19 @@ function odbc_gettypeinfo(Odbc\Connection $odbc, int $data_type = 0): Odbc\Resul function odbc_primarykeys(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table): Odbc\Result|false {} -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) function odbc_procedurecolumns(Odbc\Connection $odbc, ?string $catalog = null, ?string $schema = null, ?string $procedure = null, ?string $column = null): Odbc\Result|false {} function odbc_procedures(Odbc\Connection $odbc, ?string $catalog = null, ?string $schema = null, ?string $procedure = null): Odbc\Result|false {} function odbc_foreignkeys(Odbc\Connection $odbc, ?string $pk_catalog, string $pk_schema, string $pk_table, string $fk_catalog, string $fk_schema, string $fk_table): Odbc\Result|false {} -#endif function odbc_specialcolumns(Odbc\Connection $odbc, int $type, ?string $catalog, string $schema, string $table, int $scope, int $nullable): Odbc\Result|false {} function odbc_statistics(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table, int $unique, int $accuracy): Odbc\Result|false {} -#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) function odbc_tableprivileges(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table): Odbc\Result|false {} function odbc_columnprivileges(Odbc\Connection $odbc, ?string $catalog, string $schema, string $table, string $column): Odbc\Result|false {} -#endif /* odbc_utils.c */ diff --git a/ext/odbc/odbc_arginfo.h b/ext/odbc/odbc_arginfo.h index d458fee43383b..0298adf2c1c4f 100644 --- a/ext/odbc/odbc_arginfo.h +++ b/ext/odbc/odbc_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: efd913e4fcacb2949dc5392857032ab9c59c818d */ + * Stub hash: f9ba28767b256dbcea087a65aa4bb5f5b509d6f3 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_odbc_close_all, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -28,18 +28,15 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_odbc_cursor, 0, 1, MAY_BE_STRING ZEND_ARG_OBJ_INFO(0, statement, Odbc\\Result, 0) ZEND_END_ARG_INFO() -#if defined(HAVE_SQLDATASOURCES) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_odbc_data_source, 0, 2, MAY_BE_ARRAY|MAY_BE_NULL|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, odbc, Odbc\\Connection, 0) ZEND_ARG_TYPE_INFO(0, fetch_type, IS_LONG, 0) ZEND_END_ARG_INFO() -#endif #define arginfo_odbc_exec arginfo_odbc_prepare #define arginfo_odbc_do arginfo_odbc_prepare -#if defined(PHP_ODBC_HAVE_FETCH_HASH) ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_fetch_object, 0, 1, stdClass, MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, statement, Odbc\\Result, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, row, IS_LONG, 1, "null") @@ -49,7 +46,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_odbc_fetch_array, 0, 1, MAY_BE_A ZEND_ARG_OBJ_INFO(0, statement, Odbc\\Result, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, row, IS_LONG, 1, "null") ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_odbc_fetch_into, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, statement, Odbc\\Result, 0) @@ -93,11 +89,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_odbc_num_rows, 0, 1, IS_LONG, 0) ZEND_ARG_OBJ_INFO(0, statement, Odbc\\Result, 0) ZEND_END_ARG_INFO() -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_odbc_next_result, 0, 1, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, statement, Odbc\\Result, 0) ZEND_END_ARG_INFO() -#endif #define arginfo_odbc_num_fields arginfo_odbc_num_rows @@ -174,7 +168,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_primarykeys, 0, 4, Odbc ZEND_ARG_TYPE_INFO(0, table, IS_STRING, 0) ZEND_END_ARG_INFO() -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_procedurecolumns, 0, 1, Odbc\\Result, MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, odbc, Odbc\\Connection, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, catalog, IS_STRING, 1, "null") @@ -199,7 +192,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_foreignkeys, 0, 7, Odbc ZEND_ARG_TYPE_INFO(0, fk_schema, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, fk_table, IS_STRING, 0) ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_specialcolumns, 0, 7, Odbc\\Result, MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, odbc, Odbc\\Connection, 0) @@ -220,13 +212,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_statistics, 0, 6, Odbc\ ZEND_ARG_TYPE_INFO(0, accuracy, IS_LONG, 0) ZEND_END_ARG_INFO() -#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_tableprivileges, 0, 4, Odbc\\Result, MAY_BE_FALSE) - ZEND_ARG_OBJ_INFO(0, odbc, Odbc\\Connection, 0) - ZEND_ARG_TYPE_INFO(0, catalog, IS_STRING, 1) - ZEND_ARG_TYPE_INFO(0, schema, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, table, IS_STRING, 0) -ZEND_END_ARG_INFO() +#define arginfo_odbc_tableprivileges arginfo_odbc_primarykeys ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_columnprivileges, 0, 5, Odbc\\Result, MAY_BE_FALSE) ZEND_ARG_OBJ_INFO(0, odbc, Odbc\\Connection, 0) @@ -235,7 +221,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_odbc_columnprivileges, 0, 5, ZEND_ARG_TYPE_INFO(0, table, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, column, IS_STRING, 0) ZEND_END_ARG_INFO() -#endif ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_odbc_connection_string_is_quoted, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) @@ -253,14 +238,10 @@ ZEND_FUNCTION(odbc_longreadlen); ZEND_FUNCTION(odbc_prepare); ZEND_FUNCTION(odbc_execute); ZEND_FUNCTION(odbc_cursor); -#if defined(HAVE_SQLDATASOURCES) ZEND_FUNCTION(odbc_data_source); -#endif ZEND_FUNCTION(odbc_exec); -#if defined(PHP_ODBC_HAVE_FETCH_HASH) ZEND_FUNCTION(odbc_fetch_object); ZEND_FUNCTION(odbc_fetch_array); -#endif ZEND_FUNCTION(odbc_fetch_into); ZEND_FUNCTION(odbc_fetch_row); ZEND_FUNCTION(odbc_result); @@ -270,9 +251,7 @@ ZEND_FUNCTION(odbc_connect); ZEND_FUNCTION(odbc_pconnect); ZEND_FUNCTION(odbc_close); ZEND_FUNCTION(odbc_num_rows); -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) ZEND_FUNCTION(odbc_next_result); -#endif ZEND_FUNCTION(odbc_num_fields); ZEND_FUNCTION(odbc_field_name); ZEND_FUNCTION(odbc_field_type); @@ -289,17 +268,13 @@ ZEND_FUNCTION(odbc_tables); ZEND_FUNCTION(odbc_columns); ZEND_FUNCTION(odbc_gettypeinfo); ZEND_FUNCTION(odbc_primarykeys); -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) ZEND_FUNCTION(odbc_procedurecolumns); ZEND_FUNCTION(odbc_procedures); ZEND_FUNCTION(odbc_foreignkeys); -#endif ZEND_FUNCTION(odbc_specialcolumns); ZEND_FUNCTION(odbc_statistics); -#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) ZEND_FUNCTION(odbc_tableprivileges); ZEND_FUNCTION(odbc_columnprivileges); -#endif ZEND_FUNCTION(odbc_connection_string_is_quoted); ZEND_FUNCTION(odbc_connection_string_should_quote); ZEND_FUNCTION(odbc_connection_string_quote); @@ -311,15 +286,11 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(odbc_prepare, arginfo_odbc_prepare) ZEND_FE(odbc_execute, arginfo_odbc_execute) ZEND_FE(odbc_cursor, arginfo_odbc_cursor) -#if defined(HAVE_SQLDATASOURCES) ZEND_FE(odbc_data_source, arginfo_odbc_data_source) -#endif ZEND_FE(odbc_exec, arginfo_odbc_exec) ZEND_RAW_FENTRY("odbc_do", zif_odbc_exec, arginfo_odbc_do, 0, NULL, NULL) -#if defined(PHP_ODBC_HAVE_FETCH_HASH) ZEND_FE(odbc_fetch_object, arginfo_odbc_fetch_object) ZEND_FE(odbc_fetch_array, arginfo_odbc_fetch_array) -#endif ZEND_FE(odbc_fetch_into, arginfo_odbc_fetch_into) ZEND_FE(odbc_fetch_row, arginfo_odbc_fetch_row) ZEND_FE(odbc_result, arginfo_odbc_result) @@ -329,9 +300,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(odbc_pconnect, arginfo_odbc_pconnect) ZEND_FE(odbc_close, arginfo_odbc_close) ZEND_FE(odbc_num_rows, arginfo_odbc_num_rows) -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) ZEND_FE(odbc_next_result, arginfo_odbc_next_result) -#endif ZEND_FE(odbc_num_fields, arginfo_odbc_num_fields) ZEND_FE(odbc_field_name, arginfo_odbc_field_name) ZEND_FE(odbc_field_type, arginfo_odbc_field_type) @@ -349,17 +318,13 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(odbc_columns, arginfo_odbc_columns) ZEND_FE(odbc_gettypeinfo, arginfo_odbc_gettypeinfo) ZEND_FE(odbc_primarykeys, arginfo_odbc_primarykeys) -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) ZEND_FE(odbc_procedurecolumns, arginfo_odbc_procedurecolumns) ZEND_FE(odbc_procedures, arginfo_odbc_procedures) ZEND_FE(odbc_foreignkeys, arginfo_odbc_foreignkeys) -#endif ZEND_FE(odbc_specialcolumns, arginfo_odbc_specialcolumns) ZEND_FE(odbc_statistics, arginfo_odbc_statistics) -#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) ZEND_FE(odbc_tableprivileges, arginfo_odbc_tableprivileges) ZEND_FE(odbc_columnprivileges, arginfo_odbc_columnprivileges) -#endif ZEND_FE(odbc_connection_string_is_quoted, arginfo_odbc_connection_string_is_quoted) ZEND_FE(odbc_connection_string_should_quote, arginfo_odbc_connection_string_should_quote) ZEND_FE(odbc_connection_string_quote, arginfo_odbc_connection_string_quote) @@ -408,7 +373,6 @@ static void register_odbc_symbols(int module_number) REGISTER_LONG_CONSTANT("SQL_DATE", SQL_DATE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQL_TIME", SQL_TIME, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQL_TIMESTAMP", SQL_TIMESTAMP, CONST_PERSISTENT); -#if (defined(ODBCVER) && (ODBCVER >= 0x0300)) REGISTER_LONG_CONSTANT("SQL_TYPE_DATE", SQL_TYPE_DATE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQL_TYPE_TIME", SQL_TYPE_TIME, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQL_TYPE_TIMESTAMP", SQL_TYPE_TIMESTAMP, CONST_PERSISTENT); @@ -426,14 +390,10 @@ static void register_odbc_symbols(int module_number) REGISTER_LONG_CONSTANT("SQL_INDEX_ALL", SQL_INDEX_ALL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQL_ENSURE", SQL_ENSURE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SQL_QUICK", SQL_QUICK, CONST_PERSISTENT); -#endif zend_attribute *attribute_Deprecated_func_odbc_result_all_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "odbc_result_all", sizeof("odbc_result_all") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_odbc_result_all_0_arg0; - zend_string *attribute_Deprecated_func_odbc_result_all_0_arg0_str = zend_string_init("8.1", strlen("8.1"), 1); - ZVAL_STR(&attribute_Deprecated_func_odbc_result_all_0_arg0, attribute_Deprecated_func_odbc_result_all_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_odbc_result_all_0->args[0].value, &attribute_Deprecated_func_odbc_result_all_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_odbc_result_all_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); attribute_Deprecated_func_odbc_result_all_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "odbc_connect", sizeof("odbc_connect") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 7bc3a8bc17d05..7a6bc28718258 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -253,10 +253,6 @@ static void odbc_result_free(odbc_result *res) /* If aborted via timer expiration, don't try to call any unixODBC function */ if (res->stmt && !(PG(connection_status) & PHP_CONNECTION_TIMEOUT)) { -#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35) - SQLTransact(res->conn_ptr->henv, res->conn_ptr->hdbc, - (SQLUSMALLINT) SQL_COMMIT); -#endif SQLFreeStmt(res->stmt,SQL_DROP); /* We don't want the connection to be closed after the last statement has been closed * Connections will be closed on shutdown @@ -346,21 +342,21 @@ static void _close_odbc_pconn(zend_resource *rsrc) /* {{{ PHP_INI_DISP(display_link_nums) */ static PHP_INI_DISP(display_link_nums) { - char *value; + const zend_string *value; if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) { - value = ZSTR_VAL(ini_entry->orig_value); + value = ini_entry->orig_value; } else if (ini_entry->value) { - value = ZSTR_VAL(ini_entry->value); + value = ini_entry->value; } else { value = NULL; } if (value) { - if (atoi(value) == -1) { + if (atoi(ZSTR_VAL(value)) == -1) { PUTS("Unlimited"); } else { - php_printf("%s", value); + php_output_write(ZSTR_VAL(value), ZSTR_LEN(value)); } } } @@ -579,10 +575,6 @@ PHP_MINFO_FUNCTION(odbc) snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ODBCG(num_links)); php_info_print_table_row(2, "Active Links", buf); php_info_print_table_row(2, "ODBC library", PHP_ODBC_TYPE); -#ifdef ODBCVER - snprintf(buf, sizeof(buf), "0x%.4x", ODBCVER); - php_info_print_table_row(2, "ODBCVER", buf); -#endif #ifndef PHP_WIN32 php_info_print_table_row(2, "ODBC_CFLAGS", PHP_ODBC_CFLAGS); php_info_print_table_row(2, "ODBC_LFLAGS", PHP_ODBC_LFLAGS); @@ -670,7 +662,6 @@ void odbc_bindcols(odbc_result *result) SQLSMALLINT colnamelen; /* Not used */ SQLLEN displaysize; SQLUSMALLINT colfieldid; - int charextraalloc; result->values = (odbc_result_value *) safe_emalloc(sizeof(odbc_result_value), result->numcols, 0); @@ -678,13 +669,13 @@ void odbc_bindcols(odbc_result *result) result->binmode = ODBCG(defaultbinmode); for(i = 0; i < result->numcols; i++) { - charextraalloc = 0; + bool char_extra_alloc = false; colfieldid = SQL_COLUMN_DISPLAY_SIZE; - rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), PHP_ODBC_SQL_DESC_NAME, + rc = SQLColAttribute(result->stmt, (SQLUSMALLINT)(i+1), SQL_DESC_NAME, result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0); result->values[i].coltype = 0; - rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE, + rc = SQLColAttribute(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE, NULL, 0, NULL, &result->values[i].coltype); /* Don't bind LONG / BINARY columns, so that fetch behaviour can @@ -696,37 +687,22 @@ void odbc_bindcols(odbc_result *result) case SQL_VARBINARY: case SQL_LONGVARBINARY: case SQL_LONGVARCHAR: -#if defined(ODBCVER) && (ODBCVER >= 0x0300) case SQL_WLONGVARCHAR: -#endif result->values[i].value = NULL; break; - -#ifdef HAVE_ADABAS - case SQL_TIMESTAMP: - result->values[i].value = (char *)emalloc(27); - SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value, - 27, &result->values[i].vallen); - break; -#endif /* HAVE_ADABAS */ case SQL_CHAR: case SQL_VARCHAR: -#if defined(ODBCVER) && (ODBCVER >= 0x0300) case SQL_WCHAR: case SQL_WVARCHAR: colfieldid = SQL_DESC_OCTET_LENGTH; -#else - charextraalloc = 1; -#endif /* TODO: Check this is the intended behaviour */ ZEND_FALLTHROUGH; default: - rc = PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(i+1), colfieldid, + rc = SQLColAttribute(result->stmt, (SQLUSMALLINT)(i+1), colfieldid, NULL, 0, NULL, &displaysize); if (rc != SQL_SUCCESS) { displaysize = 0; } -#if defined(ODBCVER) && (ODBCVER >= 0x0300) if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && colfieldid == SQL_DESC_OCTET_LENGTH) { SQLINTEGER err; SQLCHAR errtxt[128]; @@ -742,7 +718,7 @@ void odbc_bindcols(odbc_result *result) } /* This is a quirk for ODBC 2.0 compatibility for broken driver implementations. */ - charextraalloc = 1; + char_extra_alloc = true; rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_DISPLAY_SIZE, NULL, 0, NULL, &displaysize); if (rc != SQL_SUCCESS) { @@ -756,7 +732,6 @@ void odbc_bindcols(odbc_result *result) result->values[i].value = NULL; break; } -#endif /* Workaround for drivers that report VARCHAR(MAX) columns as SQL_VARCHAR (bug #73725) */ if (SQL_VARCHAR == result->values[i].coltype && displaysize == 0) { result->values[i].coltype = SQL_LONGVARCHAR; @@ -769,7 +744,7 @@ void odbc_bindcols(odbc_result *result) displaysize += 3; } - if (charextraalloc) { + if (char_extra_alloc) { /* Since we don't know the exact # of bytes, allocate extra */ displaysize *= 4; } @@ -809,17 +784,7 @@ void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type) void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type) { odbc_result *result; -#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) - /* this seems to be necessary for Solid2.3 ( tested by - * tammy@synchronis.com) and Solid 3.0 (tested by eric@terra.telemediair.nl) - * Solid does not seem to declare a SQLINTEGER, but it does declare a - * SQL_INTEGER which does not work (despite being the same type as a SDWORD. - * Solid 3.5 does not have this issue. - */ - SDWORD len; -#else SQLLEN len; -#endif zval *pv_res; zend_long pv_num; @@ -845,7 +810,7 @@ void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type) RETURN_FALSE; } - PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len); + SQLColAttribute(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len); RETURN_LONG(len); } @@ -899,9 +864,7 @@ PHP_FUNCTION(odbc_prepare) odbc_result *result = NULL; RETCODE rc; int i; -#ifdef HAVE_SQL_EXTENDED_FETCH SQLUINTEGER scrollopts; -#endif if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_conn, odbc_connection_ce, &query, &query_len) == FAILURE) { RETURN_THROWS(); @@ -916,7 +879,7 @@ PHP_FUNCTION(odbc_prepare) result->numparams = 0; result->param_info = NULL; - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -929,21 +892,17 @@ PHP_FUNCTION(odbc_prepare) RETURN_FALSE; } -#ifdef HAVE_SQL_EXTENDED_FETCH - /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info, - whether Driver supports ExtendedFetch */ rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL); if (rc == SQL_SUCCESS) { if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) { /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other type if not possible. */ - SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype)); + SQLSetStmtAttr(result->stmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) ODBCG(default_cursortype), 0); } } else { result->fetch_abs = 0; } -#endif rc = SQLPrepare(result->stmt, (SQLCHAR *) query, SQL_NTS); switch (rc) { @@ -1015,10 +974,9 @@ PHP_FUNCTION(odbc_execute) zval *pv_res, *tmp; HashTable *pv_param_ht = (HashTable *) &zend_empty_array; odbc_params_t *params = NULL; - char *filename; SQLSMALLINT ctype; odbc_result *result; - int i, ne; + int i; RETCODE rc; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|h", &pv_res, odbc_result_ce, &pv_param_ht) == FAILURE) { @@ -1029,8 +987,9 @@ PHP_FUNCTION(odbc_execute) CHECK_ODBC_RESULT(result); if (result->numparams > 0) { - if ((ne = zend_hash_num_elements(pv_param_ht)) < result->numparams) { - php_error_docref(NULL, E_WARNING, "Not enough parameters (%d should be %d) given", ne, result->numparams); + uint32_t ne = zend_hash_num_elements(pv_param_ht); + if (ne < result->numparams) { + php_error_docref(NULL, E_WARNING, "Not enough parameters (%" PRIu32 " should be %d) given", ne, result->numparams); RETURN_FALSE; } @@ -1063,11 +1022,11 @@ PHP_FUNCTION(odbc_execute) ZSTR_VAL(tmpstr)[0] == '\'' && ZSTR_VAL(tmpstr)[ZSTR_LEN(tmpstr) - 1] == '\'') { - if (ZSTR_LEN(tmpstr) != strlen(ZSTR_VAL(tmpstr))) { + if (UNEXPECTED(zend_str_has_nul_byte(tmpstr))) { odbc_release_params(result, params); RETURN_FALSE; } - filename = estrndup(&ZSTR_VAL(tmpstr)[1], ZSTR_LEN(tmpstr) - 2); + char *filename = estrndup(&ZSTR_VAL(tmpstr)[1], ZSTR_LEN(tmpstr) - 2); /* Check the basedir */ if (php_check_open_basedir(filename)) { @@ -1092,9 +1051,6 @@ PHP_FUNCTION(odbc_execute) (void *)(intptr_t)params[i-1].fp, 0, ¶ms[i-1].vallen); } else { -#ifdef HAVE_DBMAKER - precision = params[i-1].vallen; -#endif if (otype == IS_NULL) { params[i-1].vallen = SQL_NULL_DATA; } @@ -1222,7 +1178,6 @@ PHP_FUNCTION(odbc_cursor) } /* }}} */ -#ifdef HAVE_SQLDATASOURCES /* {{{ Return information about the currently connected data source */ PHP_FUNCTION(odbc_data_source) { @@ -1278,7 +1233,6 @@ PHP_FUNCTION(odbc_data_source) } /* }}} */ -#endif /* HAVE_SQLDATASOURCES */ /* {{{ Prepare and execute an SQL statement */ /* XXX Use flags */ @@ -1289,9 +1243,7 @@ PHP_FUNCTION(odbc_exec) size_t query_len; odbc_result *result = NULL; RETCODE rc; -#ifdef HAVE_SQL_EXTENDED_FETCH SQLUINTEGER scrollopts; -#endif if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &pv_conn, odbc_connection_ce, &query, &query_len) == FAILURE) { RETURN_THROWS(); @@ -1303,7 +1255,7 @@ PHP_FUNCTION(odbc_exec) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -1316,21 +1268,17 @@ PHP_FUNCTION(odbc_exec) RETURN_FALSE; } -#ifdef HAVE_SQL_EXTENDED_FETCH - /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info, - whether Driver supports ExtendedFetch */ rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL); if (rc == SQL_SUCCESS) { if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) { /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other type if not possible. */ - SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype)); + SQLSetStmtAttr(result->stmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) ODBCG(default_cursortype), 0); } } else { result->fetch_abs = 0; } -#endif rc = SQLExecDirect(result->stmt, (SQLCHAR *) query, SQL_NTS); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) { @@ -1358,7 +1306,6 @@ PHP_FUNCTION(odbc_exec) } /* }}} */ -#ifdef PHP_ODBC_HAVE_FETCH_HASH #define ODBC_NUM 1 #define ODBC_OBJECT 2 @@ -1373,10 +1320,8 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) zend_long pv_row = 0; bool pv_row_is_null = true; zval *pv_res, tmp; -#ifdef HAVE_SQL_EXTENDED_FETCH SQLULEN crow; SQLUSMALLINT RowStatus[1]; -#endif if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l!", &pv_res, odbc_result_ce, &pv_row, &pv_row_is_null) == FAILURE) { RETURN_THROWS(); @@ -1387,46 +1332,33 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) /* TODO deprecate $row argument values less than 1 after PHP 8.4 */ -#ifndef HAVE_SQL_EXTENDED_FETCH - if (!pv_row_is_null && pv_row > 0) { - php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored"); - } -#endif - if (result->numcols == 0) { php_error_docref(NULL, E_WARNING, "No tuples available at this result index"); RETURN_FALSE; } -#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) { if (!pv_row_is_null && pv_row > 0) { rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus); } else { rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); } - } else -#endif - rc = SQLFetch(result->stmt); + } else { + rc = SQLFetch(result->stmt); + } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if (rc == SQL_ERROR) { -#ifdef HAVE_SQL_EXTENDED_FETCH odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch"); -#else - odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch"); -#endif } RETURN_FALSE; } array_init(return_value); -#ifdef HAVE_SQL_EXTENDED_FETCH if (!pv_row_is_null && pv_row > 0 && result->fetch_abs) result->fetched = (SQLLEN)pv_row; else -#endif result->fetched++; for(i = 0; i < result->numcols; i++) { @@ -1445,9 +1377,7 @@ static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type) } ZEND_FALLTHROUGH; case SQL_LONGVARCHAR: -#if defined(ODBCVER) && (ODBCVER >= 0x0300) case SQL_WLONGVARCHAR: -#endif if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) { ZVAL_EMPTY_STRING(&tmp); break; @@ -1527,7 +1457,6 @@ PHP_FUNCTION(odbc_fetch_array) php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT); } /* }}} */ -#endif /* {{{ Fetch one result row into an array */ PHP_FUNCTION(odbc_fetch_into) @@ -1540,10 +1469,8 @@ PHP_FUNCTION(odbc_fetch_into) zval *pv_res, *pv_res_arr, tmp; zend_long pv_row = 0; bool pv_row_is_null = true; -#ifdef HAVE_SQL_EXTENDED_FETCH SQLULEN crow; SQLUSMALLINT RowStatus[1]; -#endif /* HAVE_SQL_EXTENDED_FETCH */ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oz|l!", &pv_res, odbc_result_ce, &pv_res_arr, &pv_row, &pv_row_is_null) == FAILURE) { RETURN_THROWS(); @@ -1554,12 +1481,6 @@ PHP_FUNCTION(odbc_fetch_into) /* TODO deprecate $row argument values less than 1 after PHP 8.4 */ -#ifndef HAVE_SQL_EXTENDED_FETCH - if (!pv_row_is_null && pv_row > 0) { - php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored"); - } -#endif - if (result->numcols == 0) { php_error_docref(NULL, E_WARNING, "No tuples available at this result index"); RETURN_FALSE; @@ -1570,33 +1491,26 @@ PHP_FUNCTION(odbc_fetch_into) RETURN_THROWS(); } -#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) { if (!pv_row_is_null && pv_row > 0) { rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus); } else { rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); } - } else -#endif + } else { rc = SQLFetch(result->stmt); + } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if (rc == SQL_ERROR) { -#ifdef HAVE_SQL_EXTENDED_FETCH odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch"); -#else - odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch"); -#endif } RETURN_FALSE; } -#ifdef HAVE_SQL_EXTENDED_FETCH if (!pv_row_is_null && pv_row > 0 && result->fetch_abs) result->fetched = (SQLLEN)pv_row; else -#endif result->fetched++; for(i = 0; i < result->numcols; i++) { @@ -1615,9 +1529,7 @@ PHP_FUNCTION(odbc_fetch_into) /* TODO: Check this is the intended behaviour */ ZEND_FALLTHROUGH; case SQL_LONGVARCHAR: -#if defined(ODBCVER) && (ODBCVER >= 0x0300) case SQL_WLONGVARCHAR: -#endif if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) { ZVAL_EMPTY_STRING(&tmp); break; @@ -1676,10 +1588,8 @@ PHP_FUNCTION(odbc_fetch_row) zval *pv_res; zend_long pv_row = 0; bool pv_row_is_null = true; -#ifdef HAVE_SQL_EXTENDED_FETCH SQLULEN crow; SQLUSMALLINT RowStatus[1]; -#endif if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l!", &pv_res, odbc_result_ce, &pv_row, &pv_row_is_null) == FAILURE) { RETURN_THROWS(); @@ -1688,50 +1598,38 @@ PHP_FUNCTION(odbc_fetch_row) result = Z_ODBC_RESULT_P(pv_res); CHECK_ODBC_RESULT(result); -#ifndef HAVE_SQL_EXTENDED_FETCH - if (!pv_row_is_null) { - php_error_docref(NULL, E_WARNING, "Extended fetch functionality is not available, argument #3 ($row) is ignored"); - } -#else if (!pv_row_is_null && pv_row < 1) { php_error_docref(NULL, E_WARNING, "Argument #3 ($row) must be greater than or equal to 1"); RETURN_FALSE; } -#endif if (result->numcols == 0) { php_error_docref(NULL, E_WARNING, "No tuples available at this result index"); RETURN_FALSE; } -#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) { if (!pv_row_is_null) { rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,(SQLLEN)pv_row,&crow,RowStatus); } else { rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); } - } else -#endif + } else { rc = SQLFetch(result->stmt); + } if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if (rc == SQL_ERROR) { -#ifdef HAVE_SQL_EXTENDED_FETCH odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch"); -#else - odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch"); -#endif } RETURN_FALSE; } -#ifdef HAVE_SQL_EXTENDED_FETCH if (!pv_row_is_null) { result->fetched = (SQLLEN)pv_row; - } else -#endif + } else { result->fetched++; + } RETURN_TRUE; } @@ -1750,10 +1648,8 @@ PHP_FUNCTION(odbc_result) RETCODE rc; SQLLEN fieldsize; zval *pv_res; -#ifdef HAVE_SQL_EXTENDED_FETCH SQLULEN crow; SQLUSMALLINT RowStatus[1]; -#endif ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_OBJECT_OF_CLASS(pv_res, odbc_result_ce) @@ -1804,20 +1700,14 @@ PHP_FUNCTION(odbc_result) if (result->fetched == 0) { /* User forgot to call odbc_fetch_row(), or wants to reload the results, do it now */ -#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) rc = SQLExtendedFetch(result->stmt, SQL_FETCH_NEXT, 1, &crow,RowStatus); else -#endif rc = SQLFetch(result->stmt); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { if (rc == SQL_ERROR) { -#ifdef HAVE_SQL_EXTENDED_FETCH - odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch"); -#else - odbc_sql_error(result->conn_ptr, result->stmt, "SQLFetch"); -#endif + odbc_sql_error(result->conn_ptr, result->stmt, "SQLExtendedFetch"); } RETURN_FALSE; } @@ -1839,9 +1729,7 @@ PHP_FUNCTION(odbc_result) ZEND_FALLTHROUGH; case SQL_LONGVARCHAR: -#if defined(ODBCVER) && (ODBCVER >= 0x0300) case SQL_WLONGVARCHAR: -#endif if (IS_SQL_LONG(result->values[field_ind].coltype)) { if (result->longreadlen <= 0) { break; @@ -1849,7 +1737,7 @@ PHP_FUNCTION(odbc_result) fieldsize = result->longreadlen; } } else { - PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)(field_ind + 1), + SQLColAttribute(result->stmt, (SQLUSMALLINT)(field_ind + 1), (SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH : SQL_COLUMN_DISPLAY_SIZE), NULL, 0, NULL, &fieldsize); @@ -1885,10 +1773,7 @@ PHP_FUNCTION(odbc_result) /* Reduce fieldlen by 1 if we have char data. One day we might have binary strings... */ if ((result->values[field_ind].coltype == SQL_LONGVARCHAR) -#if defined(ODBCVER) && (ODBCVER >= 0x0300) - || (result->values[field_ind].coltype == SQL_WLONGVARCHAR) -#endif - ) { + || (result->values[field_ind].coltype == SQL_WLONGVARCHAR)) { fieldsize -= 1; } /* Don't duplicate result, saves one emalloc. @@ -1965,10 +1850,8 @@ PHP_FUNCTION(odbc_result_all) char *pv_format = NULL; size_t i, pv_format_len = 0; SQLSMALLINT sql_c_type; -#ifdef HAVE_SQL_EXTENDED_FETCH SQLULEN crow; SQLUSMALLINT RowStatus[1]; -#endif if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s", &pv_res, odbc_result_ce, &pv_format, &pv_format_len) == FAILURE) { RETURN_THROWS(); @@ -1981,11 +1864,9 @@ PHP_FUNCTION(odbc_result_all) php_error_docref(NULL, E_WARNING, "No tuples available at this result index"); RETURN_FALSE; } -#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); else -#endif rc = SQLFetch(result->stmt); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { @@ -2024,9 +1905,7 @@ PHP_FUNCTION(odbc_result_all) /* TODO: Check this is the intended behaviour */ ZEND_FALLTHROUGH; case SQL_LONGVARCHAR: -#if defined(ODBCVER) && (ODBCVER >= 0x0300) case SQL_WLONGVARCHAR: -#endif if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) { php_printf("Not printable"); @@ -2083,11 +1962,9 @@ PHP_FUNCTION(odbc_result_all) } php_printf("\n"); -#ifdef HAVE_SQL_EXTENDED_FETCH if (result->fetch_abs) rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus); else -#endif rc = SQLFetch(result->stmt); } php_printf("\n"); @@ -2157,20 +2034,8 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool return false; } -#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) - SQLSetConnectOption((link->connection->hdbc, SQL_TRANSLATE_OPTION, - SQL_SOLID_XLATOPT_NOCNV); -#endif -#ifdef HAVE_OPENLINK - { - char dsnbuf[1024]; - short dsnbuflen; - - rc = SQLDriverConnect(link->connection->hdbc, NULL, db, SQL_NTS, dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT); - } -#else if (cur_opt != SQL_CUR_DEFAULT) { - rc = SQLSetConnectOption(link->connection->hdbc, SQL_ODBC_CURSORS, cur_opt); + rc = SQLSetConnectAttr(link->connection->hdbc, SQL_ATTR_ODBC_CURSORS, (SQLPOINTER) (intptr_t) cur_opt, 0); if (rc != SQL_SUCCESS) { /* && rc != SQL_SUCCESS_WITH_INFO ? */ odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SQLSetConnectOption"); return false; @@ -2178,15 +2043,12 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool } /* Possible fix for bug #10250 * Needs testing on UnixODBC < 2.0.5 though. */ -#if defined(HAVE_EMPRESS) || defined(HAVE_UNIXODBC) || defined(PHP_WIN32) || defined (HAVE_IODBC) -/* * Uncomment the line above, and comment line below to fully test - * #ifdef HAVE_EMPRESS */ +#if defined(HAVE_UNIXODBC) || defined(PHP_WIN32) || defined (HAVE_IODBC) { int direct = 0; SQLCHAR dsnbuf[1024]; short dsnbuflen; - char *ldb = 0; - int ldb_len = 0; + char *ldb = NULL; /* a connection string may have = but not ; - i.e. "DSN=PHP" */ if (strstr((char*)db, "=")) { @@ -2248,7 +2110,7 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool efree(pwd_quoted); } } else { - ldb_len = strlen(db)+1; + size_t ldb_len = strlen(db)+1; ldb = (char*) emalloc(ldb_len); memcpy(ldb, db, ldb_len); } @@ -2266,7 +2128,6 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool } #else rc = SQLConnect(link->connection->hdbc, (SQLCHAR *) db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS); -#endif #endif if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SQLConnect"); @@ -2472,7 +2333,6 @@ PHP_FUNCTION(odbc_num_rows) } /* }}} */ -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) /* {{{ Checks if multiple results are available */ PHP_FUNCTION(odbc_next_result) { @@ -2519,7 +2379,6 @@ PHP_FUNCTION(odbc_next_result) } } /* }}} */ -#endif /* {{{ Get number of columns in a result */ PHP_FUNCTION(odbc_num_fields) @@ -2602,7 +2461,7 @@ PHP_FUNCTION(odbc_field_type) RETURN_FALSE; } - PHP_ODBC_SQLCOLATTRIBUTE(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL); + SQLColAttribute(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL); RETURN_STRING(tmp); } /* }}} */ @@ -2672,7 +2531,7 @@ PHP_FUNCTION(odbc_autocommit) CHECK_ODBC_CONNECTION(conn); if (!pv_onoff_is_null) { - rc = SQLSetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, pv_onoff ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF); + rc = SQLSetConnectAttr(conn->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) (intptr_t) (pv_onoff ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF), 0); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { odbc_sql_error(conn, SQL_NULL_HSTMT, "Set autocommit"); RETURN_FALSE; @@ -2681,7 +2540,7 @@ PHP_FUNCTION(odbc_autocommit) } else { SQLINTEGER status; - rc = SQLGetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (PTR)&status); + rc = SQLGetConnectAttr(conn->hdbc, SQL_ATTR_AUTOCOMMIT, &status, SQL_IS_INTEGER, NULL); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { odbc_sql_error(conn, SQL_NULL_HSTMT, "Get commit status"); RETURN_FALSE; @@ -2783,7 +2642,7 @@ PHP_FUNCTION(odbc_setoption) php_error_docref(NULL, E_WARNING, "Unable to set option for persistent connection"); RETURN_FALSE; } - rc = SQLSetConnectOption(link->connection->hdbc, (unsigned short) pv_opt, pv_val); + rc = SQLSetConnectAttr(link->connection->hdbc, pv_opt, (SQLPOINTER) pv_val, 0); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { odbc_sql_error(link->connection, SQL_NULL_HSTMT, "SetConnectOption"); RETURN_FALSE; @@ -2797,7 +2656,7 @@ PHP_FUNCTION(odbc_setoption) result = Z_ODBC_RESULT_P(pv_handle); CHECK_ODBC_RESULT(result); - rc = SQLSetStmtOption(result->stmt, (unsigned short) pv_opt, pv_val); + rc = SQLSetStmtAttr(result->stmt, pv_opt, (SQLPOINTER) pv_val, 0); if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { odbc_sql_error(result->conn_ptr, result->stmt, "SetStmtOption"); @@ -2837,7 +2696,7 @@ PHP_FUNCTION(odbc_tables) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -2902,7 +2761,7 @@ PHP_FUNCTION(odbc_columns) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -2949,7 +2808,6 @@ PHP_FUNCTION(odbc_columns) } /* }}} */ -#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* {{{ Returns a result identifier that can be used to fetch a list of columns and associated privileges for the specified table */ PHP_FUNCTION(odbc_columnprivileges) { @@ -2970,7 +2828,7 @@ PHP_FUNCTION(odbc_columnprivileges) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3009,9 +2867,7 @@ PHP_FUNCTION(odbc_columnprivileges) odbc_insert_new_result(conn, return_value); } /* }}} */ -#endif /* HAVE_DBMAKER || HAVE_SOLID*/ -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* {{{ Returns a result identifier to either a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table */ PHP_FUNCTION(odbc_foreignkeys) { @@ -3026,7 +2882,7 @@ PHP_FUNCTION(odbc_foreignkeys) RETURN_THROWS(); } -#if defined(HAVE_DBMAKER) || defined(HAVE_IBMDB2) +#if defined(HAVE_IBMDB2) #define EMPTY_TO_NULL(xstr) \ if ((int)strlen((xstr)) == 0) (xstr) = NULL @@ -3044,7 +2900,7 @@ PHP_FUNCTION(odbc_foreignkeys) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3085,7 +2941,6 @@ PHP_FUNCTION(odbc_foreignkeys) odbc_insert_new_result(conn, return_value); } /* }}} */ -#endif /* HAVE_SOLID */ /* {{{ Returns a result identifier containing information about data types supported by the data source */ PHP_FUNCTION(odbc_gettypeinfo) @@ -3108,7 +2963,7 @@ PHP_FUNCTION(odbc_gettypeinfo) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3163,7 +3018,7 @@ PHP_FUNCTION(odbc_primarykeys) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3202,7 +3057,6 @@ PHP_FUNCTION(odbc_primarykeys) } /* }}} */ -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* {{{ Returns a result identifier containing the list of input and output parameters, as well as the columns that make up the result set for the specified procedures */ PHP_FUNCTION(odbc_procedurecolumns) { @@ -3223,7 +3077,7 @@ PHP_FUNCTION(odbc_procedurecolumns) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3262,9 +3116,7 @@ PHP_FUNCTION(odbc_procedurecolumns) odbc_insert_new_result(conn, return_value); } /* }}} */ -#endif /* HAVE_SOLID */ -#if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* {{{ Returns a result identifier containing the list of procedure names in a datasource */ PHP_FUNCTION(odbc_procedures) { @@ -3284,7 +3136,7 @@ PHP_FUNCTION(odbc_procedures) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3322,7 +3174,6 @@ PHP_FUNCTION(odbc_procedures) odbc_insert_new_result(conn, return_value); } /* }}} */ -#endif /* HAVE_SOLID */ /* {{{ Returns a result identifier containing either the optimal set of columns that uniquely identifies a row in the table or columns that are automatically updated when any value in the row is updated by a transaction */ PHP_FUNCTION(odbc_specialcolumns) @@ -3350,7 +3201,7 @@ PHP_FUNCTION(odbc_specialcolumns) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3416,7 +3267,7 @@ PHP_FUNCTION(odbc_statistics) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3457,7 +3308,6 @@ PHP_FUNCTION(odbc_statistics) } /* }}} */ -#if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* {{{ Returns a result identifier containing a list of tables and the privileges associated with each table */ PHP_FUNCTION(odbc_tableprivileges) { @@ -3477,7 +3327,7 @@ PHP_FUNCTION(odbc_tableprivileges) object_init_ex(return_value, odbc_result_ce); result = Z_ODBC_RESULT_P(return_value); - rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); + rc = SQLAllocHandle(SQL_HANDLE_STMT, conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { php_error_docref(NULL, E_WARNING, "SQLAllocStmt error 'Invalid Handle'"); zval_ptr_dtor(return_value); @@ -3515,6 +3365,5 @@ PHP_FUNCTION(odbc_tableprivileges) odbc_insert_new_result(conn, return_value); } /* }}} */ -#endif /* HAVE_DBMAKER */ #endif /* HAVE_UODBC */ diff --git a/ext/odbc/php_odbc.h b/ext/odbc/php_odbc.h index bc29623d7c2f0..6f6264a482d74 100644 --- a/ext/odbc/php_odbc.h +++ b/ext/odbc/php_odbc.h @@ -31,10 +31,6 @@ extern zend_module_entry odbc_module_entry; #include "php_version.h" #define PHP_ODBC_VERSION PHP_VERSION -#if defined(HAVE_DBMAKER) || defined(PHP_WIN32) || defined(HAVE_IBMDB2) || defined(HAVE_UNIXODBC) || defined(HAVE_IODBC) -# define PHP_ODBC_HAVE_FETCH_HASH 1 -#endif - /* user functions */ PHP_MINIT_FUNCTION(odbc); PHP_MSHUTDOWN_FUNCTION(odbc); diff --git a/ext/odbc/php_odbc_includes.h b/ext/odbc/php_odbc_includes.h index e0c6330d74498..058684c2ed033 100644 --- a/ext/odbc/php_odbc_includes.h +++ b/ext/odbc/php_odbc_includes.h @@ -23,140 +23,31 @@ /* checking in the same order as in configure.ac */ -#if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35) /* Solid Server */ - -#define ODBC_TYPE "Solid" -#if defined(HAVE_SOLID) -# include -# include -# include -#elif defined(HAVE_SOLID_30) -# include -# include -# include -#elif defined(HAVE_SOLID_35) -# include -# include -# include -# include -# include -#endif /* end: #if defined(HAVE_SOLID) */ -#undef HAVE_SQL_EXTENDED_FETCH -#define SQLSMALLINT SWORD -#define SQLUSMALLINT UWORD -#ifndef SQL_SUCCEEDED -#define SQL_SUCCEEDED(rc) (((rc)&(~1))==0) -#endif - -#elif defined(HAVE_EMPRESS) /* Empress */ - -#define ODBC_TYPE "Empress" -#include -#include -#undef HAVE_SQL_EXTENDED_FETCH - -#elif defined(HAVE_ADABAS) /* Adabas D */ - -#define ODBC_TYPE "Adabas D" -#include -#include -#include -#define HAVE_SQL_EXTENDED_FETCH 1 -#define SQL_SUCCEEDED(rc) (((rc)&(~1))==0) -#define SQLINTEGER ULONG -#define SQLUSMALLINT USHORT - -#elif defined(HAVE_SAPDB) /* SAP DB */ - -#define ODBC_TYPE "SAP DB" -#include -#include -#include -#define HAVE_SQL_EXTENDED_FETCH 1 -#define SQL_SUCCEEDED(rc) (((rc)&(~1))==0) - -#elif defined(HAVE_IODBC) /* iODBC library */ - -#ifdef CHAR -#undef CHAR -#endif - -#ifdef SQLCHAR -#undef SQLCHAR -#endif +#if defined(HAVE_IODBC) /* iODBC library */ #define ODBC_TYPE "iODBC" #include #include #include -#define HAVE_SQL_EXTENDED_FETCH 1 #elif defined(HAVE_UNIXODBC) /* unixODBC library */ -#ifdef CHAR -#undef CHAR -#endif - -#ifdef SQLCHAR -#undef SQLCHAR -#endif - #define ODBC_TYPE "unixODBC" -#undef ODBCVER -#include -#include -#define HAVE_SQL_EXTENDED_FETCH 1 - -#elif defined(HAVE_ESOOB) /* Easysoft ODBC-ODBC Bridge library */ - -#define ODBC_TYPE "ESOOB" #include #include -#define HAVE_SQL_EXTENDED_FETCH 1 - -#elif defined(HAVE_OPENLINK) /* OpenLink ODBC drivers */ - -#define ODBC_TYPE "Openlink" -#include -#include -#include -#include -#define HAVE_SQL_EXTENDED_FETCH 1 -#ifndef SQLSMALLINT -#define SQLSMALLINT SWORD -#endif -#ifndef SQLUSMALLINT -#define SQLUSMALLINT UWORD -#endif - -#elif defined(HAVE_DBMAKER) /* DBMaker */ - -#define ODBC_TYPE "DBMaker" -#undef ODBCVER -#define ODBCVER 0x0300 -#define HAVE_SQL_EXTENDED_FETCH 1 -#include - #elif defined(HAVE_CODBC) /* Custom ODBC */ #define ODBC_TYPE "Custom ODBC" -#define HAVE_SQL_EXTENDED_FETCH 1 #include #elif defined(HAVE_IBMDB2) /* DB2 CLI */ #define ODBC_TYPE "IBM DB2 CLI" -#define HAVE_SQL_EXTENDED_FETCH 1 #include -#ifdef DB268K -/* Need to include ASLM for 68K applications */ -#include -#endif #else /* MS ODBC */ -#define HAVE_SQL_EXTENDED_FETCH 1 #include #include #include @@ -176,10 +67,6 @@ #define ODBC_SQL_ENV_T SQLHANDLE #define ODBC_SQL_CONN_T SQLHANDLE #define ODBC_SQL_STMT_T SQLHANDLE -#elif defined( HAVE_SOLID_35 ) || defined( HAVE_SAPDB ) || defined ( HAVE_EMPRESS ) -#define ODBC_SQL_ENV_T SQLHENV -#define ODBC_SQL_CONN_T SQLHDBC -#define ODBC_SQL_STMT_T SQLHSTMT #else #define ODBC_SQL_ENV_T HENV #define ODBC_SQL_CONN_T HDBC @@ -220,9 +107,7 @@ typedef struct odbc_result { odbc_result_value *values; SQLSMALLINT numcols; SQLSMALLINT numparams; -# ifdef HAVE_SQL_EXTENDED_FETCH int fetch_abs; -# endif zend_long longreadlen; int binmode; int fetched; @@ -265,21 +150,8 @@ void odbc_bindcols(odbc_result *result); void odbc_sql_error(ODBC_SQL_ERROR_PARAMS); -#if defined(ODBCVER) && (ODBCVER >= 0x0300) #define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR || x == SQL_WLONGVARCHAR) -#define PHP_ODBC_SQLCOLATTRIBUTE SQLColAttribute -#define PHP_ODBC_SQLALLOCSTMT(hdbc, phstmt) SQLAllocHandle(SQL_HANDLE_STMT, hdbc, phstmt) - -#define PHP_ODBC_SQL_DESC_NAME SQL_DESC_NAME -#else -#define IS_SQL_LONG(x) (x == SQL_LONGVARBINARY || x == SQL_LONGVARCHAR) - -#define PHP_ODBC_SQLCOLATTRIBUTE SQLColAttributes -#define PHP_ODBC_SQLALLOCSTMT SQLAllocStmt - -#define PHP_ODBC_SQL_DESC_NAME SQL_COLUMN_NAME -#endif #define IS_SQL_BINARY(x) (x == SQL_BINARY || x == SQL_VARBINARY || x == SQL_LONGVARBINARY) PHP_ODBC_API ZEND_EXTERN_MODULE_GLOBALS(odbc) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 0f1f1c986985b..f0d3379534591 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -25,6 +25,7 @@ #include "zend_extensions.h" #include "zend_compile.h" #include "ZendAccelerator.h" +#include "zend_modules.h" #include "zend_persist.h" #include "zend_shared_alloc.h" #include "zend_accelerator_module.h" @@ -102,15 +103,13 @@ typedef int gid_t; #include "zend_simd.h" -ZEND_EXTENSION(); +static zend_extension opcache_extension_entry; #ifndef ZTS zend_accel_globals accel_globals; #else int accel_globals_id; -#if defined(COMPILE_DL_OPCACHE) -ZEND_TSRMLS_CACHE_DEFINE() -#endif +size_t accel_globals_offset; #endif /* Points to the structure shared across all PHP processes */ @@ -1736,19 +1735,11 @@ static void zend_accel_set_auto_globals(int mask) ZCG(auto_globals_mask) |= mask; } -static void replay_warnings(uint32_t num_warnings, zend_error_info **warnings) { - for (uint32_t i = 0; i < num_warnings; i++) { - zend_error_info *warning = warnings[i]; - zend_error_zstr_at(warning->type, warning->filename, warning->lineno, warning->message); - } -} - static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handle, int type, zend_op_array **op_array_p) { zend_persistent_script *new_persistent_script; uint32_t orig_functions_count, orig_class_count; zend_op_array *orig_active_op_array; - zval orig_user_error_handler; zend_op_array *op_array; bool do_bailout = false; accel_time_t timestamp = 0; @@ -1816,13 +1807,6 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl orig_active_op_array = CG(active_op_array); orig_functions_count = EG(function_table)->nNumUsed; orig_class_count = EG(class_table)->nNumUsed; - ZVAL_COPY_VALUE(&orig_user_error_handler, &EG(user_error_handler)); - - /* Override them with ours */ - ZVAL_UNDEF(&EG(user_error_handler)); - if (ZCG(accel_directives).record_warnings) { - zend_begin_record_errors(); - } zend_try { orig_compiler_options = CG(compiler_options); @@ -1852,13 +1836,12 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl /* Restore originals */ CG(active_op_array) = orig_active_op_array; - EG(user_error_handler) = orig_user_error_handler; - EG(record_errors) = 0; if (!op_array) { /* compilation failed */ - zend_free_recorded_errors(); if (do_bailout) { + EG(record_errors) = false; + zend_free_recorded_errors(); zend_bailout(); } return NULL; @@ -1873,10 +1856,6 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl zend_accel_move_user_functions(CG(function_table), CG(function_table)->nNumUsed - orig_functions_count, &new_persistent_script->script); zend_accel_move_user_classes(CG(class_table), CG(class_table)->nNumUsed - orig_class_count, &new_persistent_script->script); zend_accel_build_delayed_early_binding_list(new_persistent_script); - new_persistent_script->num_warnings = EG(num_errors); - new_persistent_script->warnings = EG(errors); - EG(num_errors) = 0; - EG(errors) = NULL; efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */ @@ -1958,7 +1937,7 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int } } } - replay_warnings(persistent_script->num_warnings, persistent_script->warnings); + zend_emit_recorded_errors_ex(persistent_script->num_warnings, persistent_script->warnings); if (persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask)) { zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask & ~ZCG(auto_globals_mask)); @@ -1967,14 +1946,28 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int return zend_accel_load_script(persistent_script, 1); } + zend_begin_record_errors(); + persistent_script = opcache_compile_file(file_handle, type, &op_array); if (persistent_script) { + if (ZCG(accel_directives).record_warnings) { + persistent_script->num_warnings = EG(num_errors); + persistent_script->warnings = EG(errors); + } + from_memory = false; persistent_script = cache_script_in_file_cache(persistent_script, &from_memory); + + zend_emit_recorded_errors(); + zend_free_recorded_errors(); + return zend_accel_load_script(persistent_script, from_memory); } + zend_emit_recorded_errors(); + zend_free_recorded_errors(); + return op_array; } @@ -2170,6 +2163,8 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) return accelerator_orig_compile_file(file_handle, type); } + zend_begin_record_errors(); + SHM_PROTECT(); HANDLE_UNBLOCK_INTERRUPTIONS(); persistent_script = opcache_compile_file(file_handle, type, &op_array); @@ -2181,6 +2176,11 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) */ from_shared_memory = false; if (persistent_script) { + if (ZCG(accel_directives).record_warnings) { + persistent_script->num_warnings = EG(num_errors); + persistent_script->warnings = EG(errors); + } + /* See GH-17246: we disable GC so that user code cannot be executed during the optimizer run. */ bool orig_gc_state = gc_enable(false); persistent_script = cache_script_in_shared_memory(persistent_script, key, &from_shared_memory); @@ -2193,6 +2193,8 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) if (!persistent_script) { SHM_PROTECT(); HANDLE_UNBLOCK_INTERRUPTIONS(); + zend_emit_recorded_errors(); + zend_free_recorded_errors(); return op_array; } if (from_shared_memory) { @@ -2206,6 +2208,9 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) persistent_script->dynamic_members.last_used = ZCG(request_time); SHM_PROTECT(); HANDLE_UNBLOCK_INTERRUPTIONS(); + + zend_emit_recorded_errors(); + zend_free_recorded_errors(); } else { #ifndef ZEND_WIN32 @@ -2248,7 +2253,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) SHM_PROTECT(); HANDLE_UNBLOCK_INTERRUPTIONS(); - replay_warnings(persistent_script->num_warnings, persistent_script->warnings); + zend_emit_recorded_errors_ex(persistent_script->num_warnings, persistent_script->warnings); from_shared_memory = true; } @@ -2315,7 +2320,7 @@ static zend_class_entry* zend_accel_inheritance_cache_get(zend_class_entry *ce, entry = zend_accel_inheritance_cache_find(entry, ce, parent, traits_and_interfaces, &needs_autoload); if (entry) { if (!needs_autoload) { - replay_warnings(entry->num_warnings, entry->warnings); + zend_emit_recorded_errors_ex(entry->num_warnings, entry->warnings); if (ZCSG(map_ptr_last) > CG(map_ptr_last)) { zend_map_ptr_extend(ZCSG(map_ptr_last)); } @@ -2469,9 +2474,6 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce, entry->next = proto->inheritance_cache; proto->inheritance_cache = entry; - EG(num_errors) = 0; - EG(errors) = NULL; - ZCSG(map_ptr_last) = CG(map_ptr_last); zend_shared_alloc_destroy_xlat_table(); @@ -2840,39 +2842,12 @@ static void zps_startup_failure(const char *reason, const char *api_reason, int zend_llist_del_element(&zend_extensions, NULL, (int (*)(void *, void *))cb); } -static inline zend_result accel_find_sapi(void) +/* Return whether we are running a CLI (Command LIne) SAPI for which Opcache is + * disabled when `opcache.enable_cli=0` */ +static inline bool accel_sapi_is_cli(void) { - static const char *supported_sapis[] = { - "apache", - "fastcgi", - "cli-server", - "cgi-fcgi", - "fpm-fcgi", - "fpmi-fcgi", - "apache2handler", - "litespeed", - "uwsgi", - "fuzzer", - "frankenphp", - "ngx-php", - NULL - }; - const char **sapi_name; - - if (sapi_module.name) { - for (sapi_name = supported_sapis; *sapi_name; sapi_name++) { - if (strcmp(sapi_module.name, *sapi_name) == 0) { - return SUCCESS; - } - } - if (ZCG(accel_directives).enable_cli && ( - strcmp(sapi_module.name, "cli") == 0 - || strcmp(sapi_module.name, "phpdbg") == 0)) { - return SUCCESS; - } - } - - return FAILURE; + return strcmp(sapi_module.name, "cli") == 0 + || strcmp(sapi_module.name, "phpdbg") == 0; } static zend_result zend_accel_init_shm(void) @@ -2969,9 +2944,6 @@ static zend_result zend_accel_init_shm(void) static void accel_globals_ctor(zend_accel_globals *accel_globals) { -#if defined(COMPILE_DL_OPCACHE) && defined(ZTS) - ZEND_TSRMLS_CACHE_UPDATE(); -#endif memset(accel_globals, 0, sizeof(zend_accel_globals)); accel_globals->key = zend_string_alloc(ZCG_KEY_LEN, true); GC_MAKE_PERSISTENT_LOCAL(accel_globals->key); @@ -3002,10 +2974,22 @@ static void accel_globals_dtor(zend_accel_globals *accel_globals) # include # define MAP_HUGETLB MAP_ALIGNED_SUPER # endif +# if __has_include() +# include +# endif +# if __has_include() +# include +# endif # endif -# if defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) -static zend_result accel_remap_huge_pages(void *start, size_t size, size_t real_size, const char *name, size_t offset) +# define ZEND_HUGE_PAGE_SIZE (2UL * 1024 * 1024) + +# if (defined(__linux__) || defined(__FreeBSD__)) && (defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE)) && defined(HAVE_ATTRIBUTE_ALIGNED) && defined(HAVE_ATTRIBUTE_SECTION) && __has_include() && __has_include() +static zend_result +__attribute__((section(".remap_stub"))) +__attribute__((aligned(ZEND_HUGE_PAGE_SIZE))) +zend_never_inline +accel_remap_huge_pages(void *start, size_t size, size_t real_size) { void *ret = MAP_FAILED; void *mem; @@ -3058,94 +3042,113 @@ static zend_result accel_remap_huge_pages(void *start, size_t size, size_t real_ // Given the MAP_FIXED flag the address can never diverge ZEND_ASSERT(ret == start); - zend_mmap_set_name(start, size, "zend_huge_code_pages"); + memcpy(start, mem, real_size); mprotect(start, size, PROT_READ | PROT_EXEC); + zend_mmap_set_name(start, size, "zend_huge_code_pages"); munmap(mem, size); return SUCCESS; } -static void accel_move_code_to_huge_pages(void) -{ +static int accel_dl_iterate_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) { + if (info->dlpi_name == NULL || strcmp(info->dlpi_name, "") == 0) { + *((uintptr_t*)data) = info->dlpi_addr; + return 1; + } + return 0; +} + +static zend_result accel_find_program_section(ElfW(Shdr) *section) { + + uintptr_t base_addr; + if (dl_iterate_phdr(accel_dl_iterate_phdr_callback, &base_addr) != 1) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: executable base address not found"); + return FAILURE; + } + #if defined(__linux__) - FILE *f; - long unsigned int huge_page_size = 2 * 1024 * 1024; - - f = fopen("/proc/self/maps", "r"); - if (f) { - long unsigned int start, end, offset, inode; - char perm[5], dev[10], name[MAXPATHLEN]; - int ret; - extern char *__progname; - char buffer[MAXPATHLEN]; - - while (fgets(buffer, MAXPATHLEN, f)) { - ret = sscanf(buffer, "%lx-%lx %4s %lx %9s %lu %s\n", &start, &end, perm, &offset, dev, &inode, name); - if (ret >= 6) { - /* try to find the php text segment and map it into huge pages - Lines without 'name' are going to be skipped */ - if (ret > 6 && perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/' \ - && strstr(name, __progname)) { - long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size); - long unsigned int seg_end = (end & ~(huge_page_size-1L)); - long unsigned int real_end; - - ret = fscanf(f, "%lx-", &start); - if (ret == 1 && start == seg_end + huge_page_size) { - real_end = end; - seg_end = start; - } else { - real_end = seg_end; - } + FILE *f = fopen("/proc/self/exe", "r"); +#elif defined(__FreeBSD__) + char path[4096]; + int mib[4]; + size_t len = sizeof(path); - if (seg_end > seg_start) { - zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, name); - accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, real_end - seg_start, name, offset + seg_start - start); - } - break; - } - } - } + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; /* Current process */ + + if (sysctl(mib, 4, path, &len, NULL, 0) == -1) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: sysctl(KERN_PROC_PATHNAME) failed: %s (%d)", + strerror(errno), errno); + return FAILURE; + } + + FILE *f = fopen(path, "r"); +#endif + if (!f) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fopen(/proc/self/exe) failed: %s (%d)", + strerror(errno), errno); + return FAILURE; + } + + /* Read ELF header */ + ElfW(Ehdr) ehdr; + if (!fread(&ehdr, sizeof(ehdr), 1, f)) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fread() failed: %s (%d)", + strerror(errno), errno); fclose(f); + return FAILURE; } -#elif defined(__FreeBSD__) - size_t s = 0; - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; - long unsigned int huge_page_size = 2 * 1024 * 1024; - if (sysctl(mib, 4, NULL, &s, NULL, 0) == 0) { - s = s * 4 / 3; - void *addr = mmap(NULL, s, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); - if (addr != MAP_FAILED) { - if (sysctl(mib, 4, addr, &s, NULL, 0) == 0) { - uintptr_t start = (uintptr_t)addr; - uintptr_t end = start + s; - while (start < end) { - struct kinfo_vmentry *entry = (struct kinfo_vmentry *)start; - size_t sz = entry->kve_structsize; - if (sz == 0) { - break; - } - int permflags = entry->kve_protection; - if ((permflags & KVME_PROT_READ) && !(permflags & KVME_PROT_WRITE) && - (permflags & KVME_PROT_EXEC) && entry->kve_path[0] != '\0') { - long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size); - long unsigned int seg_end = (end & ~(huge_page_size-1L)); - if (seg_end > seg_start) { - zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %lx-%lx %s \n", seg_start, seg_end, entry->kve_path); - accel_remap_huge_pages((void*)seg_start, seg_end - seg_start, seg_end - seg_start, entry->kve_path, entry->kve_offset + seg_start - start); - // First relevant segment found is our binary - break; - } - } - start += sz; - } - } - munmap(addr, s); + + /* Read section headers */ + ElfW(Shdr) shdrs[ehdr.e_shnum]; + if (fseek(f, ehdr.e_shoff, SEEK_SET) != 0) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fseek() failed: %s (%d)", + strerror(errno), errno); + fclose(f); + return FAILURE; + } + if (fread(shdrs, sizeof(shdrs[0]), ehdr.e_shnum, f) != ehdr.e_shnum) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: fread() failed: %s (%d)", + strerror(errno), errno); + fclose(f); + return FAILURE; + } + + fclose(f); + + /* Find the program section */ + for (ElfW(Half) idx = 0; idx < ehdr.e_shnum; idx++) { + ElfW(Shdr) *sh = &shdrs[idx]; + uintptr_t start = (uintptr_t)sh->sh_addr + base_addr; + zend_accel_error(ACCEL_LOG_DEBUG, "considering section %016" PRIxPTR "-%016" PRIxPTR " vs %016" PRIxPTR "\n", start, start + sh->sh_size, (uintptr_t)accel_find_program_section); + if ((uintptr_t)accel_find_program_section >= start && (uintptr_t)accel_find_program_section < start + sh->sh_size) { + *section = *sh; + section->sh_addr = (ElfW(Addr))start; + return SUCCESS; } } -#endif + + return FAILURE; +} + +static void accel_move_code_to_huge_pages(void) +{ + ElfW(Shdr) section; + if (accel_find_program_section(§ion) == FAILURE) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": opcache.huge_code_pages: program section not found"); + return; + } + + uintptr_t start = ZEND_MM_ALIGNED_SIZE_EX(section.sh_addr, ZEND_HUGE_PAGE_SIZE); + uintptr_t end = (section.sh_addr + section.sh_size) & ~(ZEND_HUGE_PAGE_SIZE-1UL); + if (end > start) { + zend_accel_error(ACCEL_LOG_DEBUG, "remap to huge page %" PRIxPTR "-%" PRIxPTR "\n", start, end); + accel_remap_huge_pages((void*)start, end - start, end - start); + } } # else static void accel_move_code_to_huge_pages(void) @@ -3156,10 +3159,15 @@ static void accel_move_code_to_huge_pages(void) # endif /* defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) */ #endif /* HAVE_HUGE_CODE_PAGES */ +void start_accel_extension(void) +{ + zend_register_extension(&opcache_extension_entry, NULL); +} + static int accel_startup(zend_extension *extension) { #ifdef ZTS - accel_globals_id = ts_allocate_id(&accel_globals_id, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor); + accel_globals_id = ts_allocate_fast_id(&accel_globals_id, &accel_globals_offset, sizeof(zend_accel_globals), (ts_allocate_ctor) accel_globals_ctor, (ts_allocate_dtor) accel_globals_dtor); #else accel_globals_ctor(&accel_globals); #endif @@ -3174,11 +3182,7 @@ static int accel_startup(zend_extension *extension) # endif #endif - if (start_accel_module() == FAILURE) { - accel_startup_ok = false; - zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!"); - return FAILURE; - } + zend_accel_register_ini_entries(); #ifdef ZEND_WIN32 if (UNEXPECTED(accel_gen_uname_id() == FAILURE)) { @@ -3197,15 +3201,9 @@ static int accel_startup(zend_extension *extension) } #endif - /* no supported SAPI found - disable acceleration and stop initialization */ - if (accel_find_sapi() == FAILURE) { + if (!ZCG(accel_directives).enable_cli && accel_sapi_is_cli()) { accel_startup_ok = false; - if (!ZCG(accel_directives).enable_cli && - strcmp(sapi_module.name, "cli") == 0) { - zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb); - } else { - zps_startup_failure("Opcode Caching is only supported in Apache, FPM, FastCGI, FrankenPHP, LiteSpeed and uWSGI SAPIs", NULL, accelerator_remove_cb); - } + zps_startup_failure("Opcode Caching is disabled for CLI", NULL, accelerator_remove_cb); return SUCCESS; } @@ -3274,6 +3272,12 @@ static zend_result accel_post_startup(void) accel_startup_ok = false; zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - probably not enough shared memory."); return SUCCESS; + case NO_SHM_BACKEND: + zend_accel_error(ACCEL_LOG_INFO, "Opcode Caching is disabled: No available SHM backend. Set opcache.enable=0 to hide this message."); + zps_startup_failure("No available SHM backend", NULL, accelerator_remove_cb); + /* Do not abort PHP startup */ + return SUCCESS; + case SUCCESSFULLY_REATTACHED: #ifdef HAVE_JIT reattached = true; @@ -3509,6 +3513,8 @@ void accel_shutdown(void) if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), "include_path", sizeof("include_path")-1)) != NULL) { ini_entry->on_modify = orig_include_path_on_modify; } + + accel_startup_ok = false; } void zend_accel_schedule_restart(zend_accel_restart_reason reason) @@ -4198,6 +4204,24 @@ static void preload_link(void) preload_remove_declares(op_array); } } ZEND_HASH_FOREACH_END(); + + if (ce->num_hooked_props > 0) { + zend_property_info *info; + + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, info) { + if (info->hooks) { + for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { + if (info->hooks[i]) { + op_array = &info->hooks[i]->op_array; + ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION); + if (!(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { + preload_remove_declares(op_array); + } + } + } + } + } ZEND_HASH_FOREACH_END(); + } } ZEND_HASH_FOREACH_END(); } @@ -4858,6 +4882,8 @@ static zend_result accel_finish_startup_preload(bool in_child) bool old_reset_signals = SIGG(reset); #endif + ZCG(preloading) = true; + sapi_module.activate = NULL; sapi_module.deactivate = NULL; sapi_module.register_server_variables = NULL; @@ -4939,6 +4965,8 @@ static zend_result accel_finish_startup_preload(bool in_child) sapi_module.ub_write = orig_ub_write; sapi_module.flush = orig_flush; + ZCG(preloading) = false; + sapi_activate(); return ret; @@ -5005,6 +5033,7 @@ static zend_result accel_finish_startup_preload_subprocess(pid_t *pid) zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid); exit(1); } + php_child_init(); } return SUCCESS; @@ -5084,7 +5113,7 @@ static void accel_activate(void) { } } -ZEND_EXT_API zend_extension zend_extension_entry = { +static zend_extension opcache_extension_entry = { ACCELERATOR_PRODUCT_NAME, /* name */ PHP_VERSION, /* version */ "Zend Technologies", /* author */ diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index 1bac9af9b8b7a..524a6f5e12139 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -220,6 +220,7 @@ typedef struct _zend_accel_globals { #endif void *preloaded_internal_run_time_cache; size_t preloaded_internal_run_time_cache_size; + bool preloading; /* preallocated shared-memory block to save current script */ void *mem; zend_persistent_script *current_persistent_script; @@ -300,11 +301,9 @@ extern zend_accel_shared_globals *accel_shared_globals; #define ZCSG(element) (accel_shared_globals->element) #ifdef ZTS -# define ZCG(v) ZEND_TSRMG(accel_globals_id, zend_accel_globals *, v) +# define ZCG(v) ZEND_TSRMG_FAST(accel_globals_offset, zend_accel_globals *, v) extern int accel_globals_id; -# ifdef COMPILE_DL_OPCACHE -ZEND_TSRMLS_CACHE_EXTERN() -# endif +extern size_t accel_globals_offset; #else # define ZCG(v) (accel_globals.v) extern zend_accel_globals accel_globals; @@ -314,6 +313,7 @@ extern const char *zps_api_failure_reason; BEGIN_EXTERN_C() +void start_accel_extension(void); void accel_shutdown(void); ZEND_RINIT_FUNCTION(zend_accelerator); zend_result accel_post_deactivate(void); diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index 8f6d5ab711b28..70138726c56e3 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -1,9 +1,3 @@ -PHP_ARG_ENABLE([opcache], - [whether to enable Zend OPcache support], - [AS_HELP_STRING([--disable-opcache], - [Disable Zend OPcache support])], - [yes]) - PHP_ARG_ENABLE([huge-code-pages], [whether to enable copying PHP CODE pages into HUGE PAGES], [AS_HELP_STRING([--disable-huge-code-pages], @@ -25,89 +19,93 @@ PHP_ARG_WITH([capstone], [no], [no]) -if test "$PHP_OPCACHE" != "no"; then - dnl Always build as shared extension. - ext_shared=yes +AS_VAR_IF([PHP_HUGE_CODE_PAGES], [yes], + [AC_DEFINE([HAVE_HUGE_CODE_PAGES], [1], + [Define to 1 to enable copying PHP CODE pages into HUGE PAGES.])]) + +AS_VAR_IF([PHP_OPCACHE_JIT], [yes], [ + AS_CASE([$host_cpu], + [[i[34567]86*|x86*|aarch64|amd64]], [], + [ + AC_MSG_WARN([JIT not supported by host architecture]) + PHP_OPCACHE_JIT=no + ]) + + if test "$host_vendor" = "apple" && test "$host_cpu" = "aarch64" && test "$PHP_THREAD_SAFETY" = "yes"; then + AC_MSG_WARN([JIT not supported on Apple Silicon with ZTS]) + PHP_OPCACHE_JIT=no + fi +]) + +AS_VAR_IF([PHP_OPCACHE_JIT], [yes], [ + AC_DEFINE([HAVE_JIT], [1], [Define to 1 to enable JIT.]) + ZEND_JIT_SRC=m4_normalize([" + jit/ir/ir_cfg.c + jit/ir/ir_check.c + jit/ir/ir_dump.c + jit/ir/ir_emit.c + jit/ir/ir_gcm.c + jit/ir/ir_gdb.c + jit/ir/ir_patch.c + jit/ir/ir_perf.c + jit/ir/ir_ra.c + jit/ir/ir_save.c + jit/ir/ir_sccp.c + jit/ir/ir_strtab.c + jit/ir/ir.c + jit/zend_jit_vm_helpers.c + jit/zend_jit.c + "]) + + dnl Find out which ABI we are using. + AS_CASE([$host_alias], + [x86_64-*-darwin*], [ + IR_TARGET=IR_TARGET_X64 + DASM_FLAGS="-D X64APPLE=1 -D X64=1" + DASM_ARCH="x86" + TLS_TARGET="darwin" + ], + [*x86_64*|amd64-*-freebsd*], [ + IR_TARGET=IR_TARGET_X64 + DASM_FLAGS="-D X64=1" + DASM_ARCH="x86" + TLS_TARGET="x86_64" + ], + [[i[34567]86*|x86*]], [ + IR_TARGET=IR_TARGET_X86 + DASM_ARCH="x86" + TLS_TARGET="x86" + ], + [aarch64*], [ + IR_TARGET=IR_TARGET_AARCH64 + DASM_ARCH="aarch64" + TLS_TARGET="aarch64" + ]) - AS_VAR_IF([PHP_HUGE_CODE_PAGES], [yes], - [AC_DEFINE([HAVE_HUGE_CODE_PAGES], [1], - [Define to 1 to enable copying PHP CODE pages into HUGE PAGES.])]) + AS_VAR_IF([PHP_CAPSTONE], [yes], + [PKG_CHECK_MODULES([CAPSTONE], [capstone >= 3.0.0], [ + AC_DEFINE([HAVE_CAPSTONE], [1], [Define to 1 if Capstone is available.]) + PHP_EVAL_LIBLINE([$CAPSTONE_LIBS]) + PHP_EVAL_INCLINE([$CAPSTONE_CFLAGS]) + ZEND_JIT_SRC="$ZEND_JIT_SRC jit/ir/ir_disasm.c" + ])]) - AS_VAR_IF([PHP_OPCACHE_JIT], [yes], [ - AS_CASE([$host_cpu], - [[i[34567]86*|x86*|aarch64|amd64]], [], - [ - AC_MSG_WARN([JIT not supported by host architecture]) - PHP_OPCACHE_JIT=no - ]) + PHP_SUBST([IR_TARGET]) + PHP_SUBST([DASM_FLAGS]) + PHP_SUBST([DASM_ARCH]) - if test "$host_vendor" = "apple" && test "$host_cpu" = "aarch64" && test "$PHP_THREAD_SAFETY" = "yes"; then - AC_MSG_WARN([JIT not supported on Apple Silicon with ZTS]) - PHP_OPCACHE_JIT=no - fi - ]) + JIT_CFLAGS="-I@ext_builddir@/jit/ir -D$IR_TARGET -DIR_PHP" + AS_VAR_IF([ZEND_DEBUG], [yes], [JIT_CFLAGS="$JIT_CFLAGS -DIR_DEBUG"]) - AS_VAR_IF([PHP_OPCACHE_JIT], [yes], [ - AC_DEFINE([HAVE_JIT], [1], [Define to 1 to enable JIT.]) - ZEND_JIT_SRC=m4_normalize([" - jit/ir/ir_cfg.c - jit/ir/ir_check.c - jit/ir/ir_dump.c - jit/ir/ir_emit.c - jit/ir/ir_gcm.c - jit/ir/ir_gdb.c - jit/ir/ir_patch.c - jit/ir/ir_perf.c - jit/ir/ir_ra.c - jit/ir/ir_save.c - jit/ir/ir_sccp.c - jit/ir/ir_strtab.c - jit/ir/ir.c - jit/zend_jit_vm_helpers.c - jit/zend_jit.c - "]) - - dnl Find out which ABI we are using. - AS_CASE([$host_alias], - [x86_64-*-darwin*], [ - IR_TARGET=IR_TARGET_X64 - DASM_FLAGS="-D X64APPLE=1 -D X64=1" - DASM_ARCH="x86" - ], - [*x86_64*|amd64-*-freebsd*], [ - IR_TARGET=IR_TARGET_X64 - DASM_FLAGS="-D X64=1" - DASM_ARCH="x86" - ], - [[i[34567]86*|x86*]], [ - IR_TARGET=IR_TARGET_X86 - DASM_ARCH="x86" - ], - [aarch64*], [ - IR_TARGET=IR_TARGET_AARCH64 - DASM_ARCH="aarch64" - ]) - - AS_VAR_IF([PHP_CAPSTONE], [yes], - [PKG_CHECK_MODULES([CAPSTONE], [capstone >= 3.0.0], [ - AC_DEFINE([HAVE_CAPSTONE], [1], [Define to 1 if Capstone is available.]) - PHP_EVAL_LIBLINE([$CAPSTONE_LIBS], [OPCACHE_SHARED_LIBADD]) - PHP_EVAL_INCLINE([$CAPSTONE_CFLAGS]) - ZEND_JIT_SRC="$ZEND_JIT_SRC jit/ir/ir_disasm.c" - ])]) - - PHP_SUBST([IR_TARGET]) - PHP_SUBST([DASM_FLAGS]) - PHP_SUBST([DASM_ARCH]) - - JIT_CFLAGS="-I@ext_builddir@/jit/ir -D$IR_TARGET -DIR_PHP" - AS_VAR_IF([ZEND_DEBUG], [yes], [JIT_CFLAGS="$JIT_CFLAGS -DIR_DEBUG"]) + AS_VAR_IF([PHP_THREAD_SAFETY], [yes], [ + ZEND_JIT_SRC="$ZEND_JIT_SRC jit/tls/zend_jit_tls_$TLS_TARGET.c" ]) +]) - AC_CHECK_FUNCS([mprotect shm_create_largepage]) +AC_CHECK_FUNCS([mprotect shm_create_largepage]) - AC_CACHE_CHECK([for sysvipc shared memory support], [php_cv_shm_ipc], - [AC_RUN_IFELSE([AC_LANG_SOURCE([ +AC_CACHE_CHECK([for sysvipc shared memory support], [php_cv_shm_ipc], + [AC_RUN_IFELSE([AC_LANG_SOURCE([ #include #include #include @@ -309,56 +307,60 @@ int main(void) { } return 0; }]])], - [php_cv_shm_mmap_posix=yes], - [php_cv_shm_mmap_posix=no], - [php_cv_shm_mmap_posix=no]) - ]) + [php_cv_shm_mmap_posix=yes], + [php_cv_shm_mmap_posix=no], + [php_cv_shm_mmap_posix=no]) ]) - LIBS=$LIBS_save +]) +LIBS=$LIBS_save + +AS_VAR_IF([php_cv_shm_mmap_posix], [yes], [ + AC_DEFINE([HAVE_SHM_MMAP_POSIX], [1], + [Define to 1 if you have the POSIX mmap() SHM support.]) + AS_CASE([$ac_cv_search_shm_open], ["none required"|no], [], + [PHP_EVAL_LIBLINE([$ac_cv_search_shm_open])]) +]) + +PHP_NEW_EXTENSION([opcache], m4_normalize([ + shared_alloc_mmap.c + shared_alloc_posix.c + shared_alloc_shm.c + zend_accelerator_api.c + zend_accelerator_blacklist.c + zend_accelerator_debug.c + zend_accelerator_hash.c + zend_accelerator_module.c + zend_accelerator_util_funcs.c + zend_file_cache.c + zend_persist_calc.c + zend_persist.c + zend_shared_alloc.c + ZendAccelerator.c + $ZEND_JIT_SRC + ]), + [no],, + [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 $JIT_CFLAGS],, + [yes]) - AS_VAR_IF([php_cv_shm_mmap_posix], [yes], [ - AC_DEFINE([HAVE_SHM_MMAP_POSIX], [1], - [Define to 1 if you have the POSIX mmap() SHM support.]) - AS_CASE([$ac_cv_search_shm_open], ["none required"|no], [], - [PHP_EVAL_LIBLINE([$ac_cv_search_shm_open], [OPCACHE_SHARED_LIBADD])]) - ]) +PHP_ADD_EXTENSION_DEP(opcache, date) +PHP_ADD_EXTENSION_DEP(opcache, pcre) - PHP_NEW_EXTENSION([opcache], m4_normalize([ - shared_alloc_mmap.c - shared_alloc_posix.c - shared_alloc_shm.c - zend_accelerator_blacklist.c - zend_accelerator_debug.c - zend_accelerator_hash.c - zend_accelerator_module.c - zend_accelerator_util_funcs.c - zend_file_cache.c - zend_persist_calc.c - zend_persist.c - zend_shared_alloc.c - ZendAccelerator.c - $ZEND_JIT_SRC - ]), - [$ext_shared],, - [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 $JIT_CFLAGS],, - [yes]) - - PHP_ADD_EXTENSION_DEP(opcache, date) - PHP_ADD_EXTENSION_DEP(opcache, pcre) - - if test "$php_cv_shm_ipc" != "yes" && test "$php_cv_shm_mmap_posix" != "yes" && test "$php_cv_shm_mmap_anon" != "yes"; then - AC_MSG_FAILURE(m4_text_wrap([ - No supported shared memory caching support was found when configuring - opcache. - ])) - fi +if test "$php_cv_shm_ipc" != "yes" && test "$php_cv_shm_mmap_posix" != "yes" && test "$php_cv_shm_mmap_anon" != "yes"; then + AC_MSG_WARN(m4_text_wrap([ + No supported shared memory caching support was found when configuring + opcache. Opcache will be disabled. + ])) +fi - AS_VAR_IF([PHP_OPCACHE_JIT], [yes], [ - PHP_ADD_BUILD_DIR([ - $ext_builddir/jit - $ext_builddir/jit/ir - ]) - PHP_ADD_MAKEFILE_FRAGMENT([$ext_srcdir/jit/Makefile.frag]) +AS_VAR_IF([PHP_OPCACHE_JIT], [yes], [ + PHP_ADD_BUILD_DIR([ + $ext_builddir/jit + $ext_builddir/jit/ir ]) - PHP_SUBST([OPCACHE_SHARED_LIBADD]) -fi + AS_VAR_IF([PHP_THREAD_SAFETY], [yes], [ + PHP_ADD_BUILD_DIR([$ext_builddir/jit/tls]) + ]) + PHP_ADD_MAKEFILE_FRAGMENT([$ext_srcdir/jit/Makefile.frag]) +]) + +PHP_INSTALL_HEADERS([ext/opcache], [zend_accelerator_api.h]) diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32 index fa89ca1f18a39..9b8f2a7e5107a 100644 --- a/ext/opcache/config.w32 +++ b/ext/opcache/config.w32 @@ -1,69 +1,73 @@ -ARG_ENABLE("opcache", "whether to enable Zend OPcache support", "yes"); ARG_ENABLE("opcache-jit", "whether to enable JIT (not supported for ARM64)", "yes"); +PHP_OPCACHE="yes"; -if (PHP_OPCACHE != "no") { +ZEND_EXTENSION('opcache', "\ + ZendAccelerator.c \ + zend_accelerator_api.c \ + zend_accelerator_blacklist.c \ + zend_accelerator_debug.c \ + zend_accelerator_hash.c \ + zend_accelerator_module.c \ + zend_accelerator_util_funcs.c \ + zend_persist.c \ + zend_persist_calc.c \ + zend_file_cache.c \ + zend_shared_alloc.c \ + shared_alloc_win32.c", false, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); - ZEND_EXTENSION('opcache', "\ - ZendAccelerator.c \ - zend_accelerator_blacklist.c \ - zend_accelerator_debug.c \ - zend_accelerator_hash.c \ - zend_accelerator_module.c \ - zend_accelerator_util_funcs.c \ - zend_persist.c \ - zend_persist_calc.c \ - zend_file_cache.c \ - zend_shared_alloc.c \ - shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); +ADD_EXTENSION_DEP('opcache', 'date'); +ADD_EXTENSION_DEP('opcache', 'hash'); +ADD_EXTENSION_DEP('opcache', 'pcre'); - ADD_EXTENSION_DEP('opcache', 'date'); - ADD_EXTENSION_DEP('opcache', 'hash'); - ADD_EXTENSION_DEP('opcache', 'pcre'); +if (PHP_OPCACHE_JIT == "yes") { + if (TARGET_ARCH == 'arm64') { + WARNING("JIT not enabled; not yet supported for ARM64"); + } else if (CHECK_HEADER_ADD_INCLUDE("ir/ir.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { + var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1"; + var ir_target = (X64 ? "IR_TARGET_X64" : "IR_TARGET_X86"); + var ir_src = "ir_strtab.c ir_cfg.c ir_sccp.c ir_gcm.c ir_ra.c ir_save.c \ + ir_dump.c ir_check.c ir_patch.c"; - if (PHP_OPCACHE_JIT == "yes") { - if (TARGET_ARCH == 'arm64') { - WARNING("JIT not enabled; not yet supported for ARM64"); - } else if (CHECK_HEADER_ADD_INCLUDE("ir/ir.h", "CFLAGS_OPCACHE", PHP_OPCACHE + ";ext\\opcache\\jit")) { - var dasm_flags = (X64 ? "-D X64=1" : "") + (X64 ? " -D X64WIN=1" : "") + " -D WIN=1"; - var ir_target = (X64 ? "IR_TARGET_X64" : "IR_TARGET_X86"); - var ir_src = "ir_strtab.c ir_cfg.c ir_sccp.c ir_gcm.c ir_ra.c ir_save.c \ - ir_dump.c ir_check.c ir_patch.c"; + DEFINE("IR_TARGET", ir_target); + DEFINE("DASM_FLAGS", dasm_flags); + DEFINE("DASM_ARCH", "x86"); + DEFINE("TLS_TARGET", "win"); - DEFINE("IR_TARGET", ir_target); - DEFINE("DASM_FLAGS", dasm_flags); - DEFINE("DASM_ARCH", "x86"); + AC_DEFINE('HAVE_JIT', 1, 'Define to 1 to enable JIT.'); - AC_DEFINE('HAVE_JIT', 1, 'Define to 1 to enable JIT.'); - - ADD_FLAG("CFLAGS_OPCACHE", "/I \"ext\\opcache\\jit\\ir\" /D "+ir_target+" /D IR_PHP"); - if (PHP_DEBUG == "yes") { - ADD_FLAG("CFLAGS_OPCACHE", "/D IR_DEBUG"); - } + ADD_FLAG("CFLAGS_OPCACHE", "/I \"ext\\opcache\\jit\\ir\" /D "+ir_target+" /D IR_PHP"); + if (PHP_DEBUG == "yes") { + ADD_FLAG("CFLAGS_OPCACHE", "/D IR_DEBUG"); + } - if (CHECK_HEADER_ADD_INCLUDE("capstone\\capstone.h", "CFLAGS_OPCACHE", PHP_OPCACHE+ ";" + PHP_PHP_BUILD + "\\include") && - CHECK_LIB("capstone.lib", "opcache", PHP_OPCACHE)) { - AC_DEFINE('HAVE_CAPSTONE', 1, 'Define to 1 if Capstone is available.'); - ir_src += " ir_disasm.c"; - } + if (CHECK_HEADER_ADD_INCLUDE("capstone\\capstone.h", "CFLAGS_OPCACHE", PHP_OPCACHE+ ";" + PHP_PHP_BUILD + "\\include") && + CHECK_LIB("capstone.lib", "opcache", PHP_OPCACHE)) { + AC_DEFINE('HAVE_CAPSTONE', 1, 'Define to 1 if Capstone is available.'); + ir_src += " ir_disasm.c"; + } - ADD_MAKEFILE_FRAGMENT(configure_module_dirname + "\\jit\\Makefile.frag.w32"); + ADD_MAKEFILE_FRAGMENT(configure_module_dirname + "\\jit\\Makefile.frag.w32"); - ADD_SOURCES(configure_module_dirname + "\\jit", - "zend_jit.c zend_jit_vm_helpers.c", - "opcache", "ext\\opcache\\jit"); - ADD_SOURCES(configure_module_dirname + "\\jit\\ir", - "ir.c", "opcache", "ext\\opcache\\jit\\ir"); - ADD_SOURCES(configure_module_dirname + "\\jit\\ir", - "ir_emit.c", "opcache", "ext\\opcache\\jit\\ir"); - ADD_SOURCES(configure_module_dirname + "\\jit\\ir", - ir_src, "opcache", "ext\\opcache\\jit\\ir"); - } else { - WARNING("JIT not enabled, headers not found"); + ADD_SOURCES(configure_module_dirname + "\\jit", + "zend_jit.c zend_jit_vm_helpers.c", + "opcache", "ext\\opcache\\jit"); + if (PHP_ZTS == "yes") { + ADD_SOURCES(configure_module_dirname + "\\jit\\tls", + "zend_jit_tls_win.c", + "opcache", "ext\\opcache\\jit\\tls"); } + ADD_SOURCES(configure_module_dirname + "\\jit\\ir", + "ir.c", "opcache", "ext\\opcache\\jit\\ir"); + ADD_SOURCES(configure_module_dirname + "\\jit\\ir", + "ir_emit.c", "opcache", "ext\\opcache\\jit\\ir"); + ADD_SOURCES(configure_module_dirname + "\\jit\\ir", + ir_src, "opcache", "ext\\opcache\\jit\\ir"); + } else { + WARNING("JIT not enabled, headers not found"); } - - ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname); - } +ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname); + +PHP_INSTALL_HEADERS("ext/opcache", "zend_accelerator_api.h"); diff --git a/ext/opcache/jit/Dockerfile.arm64.example b/ext/opcache/jit/Dockerfile.arm64.example index e7b6a03b2db89..6665f4ab81b75 100644 --- a/ext/opcache/jit/Dockerfile.arm64.example +++ b/ext/opcache/jit/Dockerfile.arm64.example @@ -12,4 +12,4 @@ ADD . /php-src/ WORKDIR /php-src RUN ./buildconf # Compile a minimal debug build. --enable-debug adds runtime assertions and is slower than regular builds. -RUN ./configure --enable-debug --disable-all --enable-opcache && make clean && make -j$(nproc) +RUN ./configure --enable-debug --disable-all && make clean && make -j$(nproc) diff --git a/ext/opcache/jit/README.md b/ext/opcache/jit/README.md index 6ec58378acc7e..c87c625e845bb 100644 --- a/ext/opcache/jit/README.md +++ b/ext/opcache/jit/README.md @@ -76,7 +76,7 @@ export LDFLAGS=-L/usr/lib/i386-linux-gnu export CFLAGS='-m32' export CXXFLAGS='-m32' export PKG_CONFIG=/usr/bin/i686-linux-gnu-pkg-config -./configure --disable-all --enable-opcache --build=i686-pc-linux-gnu +./configure --disable-all --build=i686-pc-linux-gnu make -j$(nproc) ``` diff --git a/ext/opcache/jit/ir/ir.c b/ext/opcache/jit/ir/ir.c index a9f55cc0e466c..9d1b698761fbb 100644 --- a/ext/opcache/jit/ir/ir.c +++ b/ext/opcache/jit/ir/ir.c @@ -172,7 +172,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted } else if (insn->val.c == '\0') { fprintf(f, "'\\0'"); } else { - fprintf(f, "%u", insn->val.c); + fprintf(f, "%u", (unsigned char)insn->val.c); } break; case IR_I8: @@ -247,6 +247,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted #define ir_op_flag_S1X1 (ir_op_flag_S | 1 | (2 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_S2 (ir_op_flag_S | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_S2X1 (ir_op_flag_S | 2 | (3 << IR_OP_FLAG_OPERANDS_SHIFT)) +#define ir_op_flag_S3 (ir_op_flag_S | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT)) #define ir_op_flag_SN (ir_op_flag_S | IR_OP_FLAG_VAR_INPUTS) #define ir_op_flag_E (IR_OP_FLAG_CONTROL|IR_OP_FLAG_BB_END) #define ir_op_flag_E1 (ir_op_flag_E | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT)) @@ -623,7 +624,7 @@ ir_ref ir_const_bool(ir_ctx *ctx, bool c) ir_ref ir_const_char(ir_ctx *ctx, char c) { ir_val val; - val.i64 = c; + val.i64 = (signed char)c; return ir_const(ctx, val, IR_CHAR); } @@ -803,7 +804,9 @@ ir_ref ir_proto(ir_ctx *ctx, uint8_t flags, ir_type ret_type, uint32_t params_co proto->flags = flags; proto->ret_type = ret_type; proto->params_count = params_count; - memcpy(proto->param_types, param_types, params_count); + if (params_count) { + memcpy(proto->param_types, param_types, params_count); + } return ir_strl(ctx, (const char *)proto, offsetof(ir_proto_t, param_types) + params_count); } @@ -1080,7 +1083,7 @@ ir_ref ir_emit_N(ir_ctx *ctx, uint32_t opt, int32_t count) ir_ref *p, ref = ctx->insns_count; ir_insn *insn; - IR_ASSERT(count >= 0); + IR_ASSERT(count >= 0 && count < 65536); while (UNEXPECTED(ref + count/4 >= ctx->insns_limit)) { ir_grow_top(ctx); } @@ -2973,6 +2976,12 @@ void _ir_CASE_VAL(ir_ctx *ctx, ir_ref switch_ref, ir_ref val) ctx->control = ir_emit2(ctx, IR_CASE_VAL, switch_ref, val); } +void _ir_CASE_RANGE(ir_ctx *ctx, ir_ref switch_ref, ir_ref v1, ir_ref v2) +{ + IR_ASSERT(!ctx->control); + ctx->control = ir_emit3(ctx, IR_CASE_RANGE, switch_ref, v1, v2); +} + void _ir_CASE_DEFAULT(ir_ctx *ctx, ir_ref switch_ref) { IR_ASSERT(!ctx->control); diff --git a/ext/opcache/jit/ir/ir.h b/ext/opcache/jit/ir/ir.h index ec5e57129c9ab..9575348ff5450 100644 --- a/ext/opcache/jit/ir/ir.h +++ b/ext/opcache/jit/ir/ir.h @@ -359,6 +359,7 @@ typedef enum _ir_type { _(IF_TRUE, S1X1, src, prb, ___) /* IF TRUE proj. */ \ _(IF_FALSE, S1X1, src, prb, ___) /* IF FALSE proj. */ \ _(CASE_VAL, S2X1, src, def, prb) /* switch proj. */ \ + _(CASE_RANGE, S3, src, def, def) /* switch proj. */ \ _(CASE_DEFAULT, S1X1, src, prb, ___) /* switch proj. */ \ _(MERGE, SN, src, src, src) /* control merge */ \ _(LOOP_BEGIN, SN, src, src, src) /* loop start */ \ @@ -854,6 +855,9 @@ void ir_gdb_unregister_all(void); bool ir_gdb_present(void); /* IR load API (implementation in ir_load.c) */ +#define IR_RESOLVE_SYM_ADD_THUNK (1<<0) +#define IR_RESOLVE_SYM_SILENT (1<<1) + struct _ir_loader { uint32_t default_func_flags; bool (*init_module) (ir_loader *loader, const char *name, const char *filename, const char *target); @@ -870,7 +874,7 @@ struct _ir_loader { bool (*sym_data_end) (ir_loader *loader, uint32_t flags); bool (*func_init) (ir_loader *loader, ir_ctx *ctx, const char *name); bool (*func_process) (ir_loader *loader, ir_ctx *ctx, const char *name); - void*(*resolve_sym_name) (ir_loader *loader, const char *name, bool add_thunk); + void*(*resolve_sym_name) (ir_loader *loader, const char *name, uint32_t flags); bool (*has_sym) (ir_loader *loader, const char *name); bool (*add_sym) (ir_loader *loader, const char *name, void *addr); }; @@ -884,11 +888,12 @@ int ir_load_llvm_bitcode(ir_loader *loader, const char *filename); int ir_load_llvm_asm(ir_loader *loader, const char *filename); /* IR save API (implementation in ir_save.c) */ -#define IR_SAVE_CFG (1<<0) /* add info about CFG */ -#define IR_SAVE_CFG_MAP (1<<1) /* add info about CFG block assignment */ -#define IR_SAVE_USE_LISTS (1<<2) /* add info about def->use lists */ -#define IR_SAVE_RULES (1<<3) /* add info about selected code-generation rules */ -#define IR_SAVE_REGS (1<<4) /* add info about selected registers */ +#define IR_SAVE_CFG (1<<0) /* add info about CFG */ +#define IR_SAVE_CFG_MAP (1<<1) /* add info about CFG block assignment */ +#define IR_SAVE_USE_LISTS (1<<2) /* add info about def->use lists */ +#define IR_SAVE_RULES (1<<3) /* add info about selected code-generation rules */ +#define IR_SAVE_REGS (1<<4) /* add info about selected registers */ +#define IR_SAVE_SAFE_NAMES (1<<5) /* add '@' prefix to symbol names */ void ir_print_proto(const ir_ctx *ctx, ir_ref proto, FILE *f); void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f); diff --git a/ext/opcache/jit/ir/ir_aarch64.dasc b/ext/opcache/jit/ir/ir_aarch64.dasc index 772eea7a5d78a..3a2c3687042cd 100644 --- a/ext/opcache/jit/ir/ir_aarch64.dasc +++ b/ext/opcache/jit/ir/ir_aarch64.dasc @@ -397,6 +397,15 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co n++; } break; + case IR_INT2FP: + case IR_FP2INT: + insn = &ctx->ir_base[ref]; + n = 0; + if (IR_IS_CONST_REF(insn->op1)) { + constraints->tmp_regs[n] = IR_TMP_REG(1, ctx->ir_base[insn->op1].type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n++; + } + break; case IR_MUL_PWR2: case IR_DIV_PWR2: case IR_MOD_PWR2: @@ -404,8 +413,6 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co case IR_SHIFT_CONST: case IR_OP_INT: case IR_OP_FP: - case IR_INT2FP: - case IR_FP2INT: case IR_FP2FP: insn = &ctx->ir_base[ref]; n = 0; @@ -996,6 +1003,7 @@ binop_fp: case IR_IF_TRUE: case IR_IF_FALSE: case IR_CASE_VAL: + case IR_CASE_RANGE: case IR_CASE_DEFAULT: case IR_MERGE: case IR_LOOP_BEGIN: @@ -1397,7 +1405,7 @@ static void ir_load_local_addr(ir_ctx *ctx, ir_reg reg, ir_ref src) | add Rx(reg), Rx(base), #offset } else { ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); - | add sp, sp, Rx(IR_REG_INT_TMP) + | add Rx(reg), sp, Rx(IR_REG_INT_TMP) } } @@ -1586,19 +1594,31 @@ static void ir_emit_prologue(ir_ctx *ctx) offset = -(ctx->stack_frame_size+16); if (aarch64_may_encode_imm7_addr_offset(offset, 8)) { | stp x29, x30, [sp, #offset]! - } else { + } else if (aarch64_may_encode_imm12(ctx->stack_frame_size+16)) { | sub sp, sp, #(ctx->stack_frame_size+16) | stp x29, x30, [sp] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size+16); + | sub sp, sp, Rx(IR_REG_INT_TMP) + | stp x29, x30, [sp] } | mov x29, sp if (ctx->call_stack_size) { - | sub sp, sp, #(ctx->call_stack_size) + if (aarch64_may_encode_imm12(ctx->call_stack_size)) { + | sub sp, sp, #(ctx->call_stack_size) + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->call_stack_size); + | sub sp, sp, Rx(IR_REG_INT_TMP) + } } } else if (ctx->stack_frame_size + ctx->call_stack_size) { if (ctx->fixed_stack_red_zone) { IR_ASSERT(ctx->stack_frame_size + ctx->call_stack_size <= ctx->fixed_stack_red_zone); + } else if (aarch64_may_encode_imm12(ctx->stack_frame_size + ctx->call_stack_size)) { + | sub sp, sp, #(ctx->stack_frame_size + ctx->call_stack_size) } else { - | sub sp, sp, #(ctx->stack_frame_size + ctx->call_stack_size) + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size + ctx->call_stack_size); + | sub sp, sp, Rx(IR_REG_INT_TMP) } } if (ctx->used_preserved_regs) { @@ -1622,26 +1642,41 @@ static void ir_emit_prologue(ir_ctx *ctx) offset -= sizeof(void*) * 2; if (aarch64_may_encode_imm7_addr_offset(offset, 8)) { | stp Rx(prev), Rx(i), [Rx(fp), #offset] - } else { - IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8)); + } else if (aarch64_may_encode_addr_offset(offset + 8, 8)) { | str Rx(prev), [Rx(fp), #offset] | str Rx(i), [Rx(fp), #(offset+8)] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + | add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8 + | str Rx(i), [Rx(fp), Rx(IR_REG_INT_TMP)] } prev = IR_REG_NONE; } else { if (prev < IR_REG_FP_FIRST) { offset -= sizeof(void*); - | str Rx(prev), [Rx(fp), #offset] - offset -= sizeof(void*); - | str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | str Rx(prev), [Rx(fp), #offset] + offset -= sizeof(void*); + | str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + | sub Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8 + | str Rd(i-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } else { offset -= sizeof(void*) * 2; if (aarch64_may_encode_imm7_addr_offset(offset, 8)) { | stp Rd(prev-IR_REG_FP_FIRST), Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset] - } else { - IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8)); + } else if (aarch64_may_encode_addr_offset(offset + 8, 8)) { | str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset] | str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #(offset+8)] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] + | add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8 + | str Rd(i-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] } } prev = IR_REG_NONE; @@ -1651,10 +1686,20 @@ static void ir_emit_prologue(ir_ctx *ctx) if (prev != IR_REG_NONE) { if (prev < IR_REG_FP_FIRST) { offset -= sizeof(void*); - | str Rx(prev), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | str Rx(prev), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } else { offset -= sizeof(void*); - | str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset, 8)) { + | str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)] + } } } } @@ -1684,10 +1729,14 @@ static void ir_emit_prologue(ir_ctx *ctx) if (prev != IR_REG_NONE) { if (aarch64_may_encode_imm7_addr_offset(offset, 8)) { | stp Rx(prev), Rx(int_reg_params[i]), [Rx(fp), #offset] - } else { - IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8)); + } else if (aarch64_may_encode_addr_offset(offset + 8, 8)) { | str Rx(prev), [Rx(fp), #offset] | str Rx(int_reg_params[i]), [Rx(fp), #(offset+8)] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + | add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8 + | str Rx(int_reg_params[i]), [Rx(fp), Rx(IR_REG_INT_TMP)] } prev = IR_REG_NONE; offset += sizeof(void*) * 2; @@ -1696,7 +1745,12 @@ static void ir_emit_prologue(ir_ctx *ctx) } } if (prev != IR_REG_NONE) { - | str Rx(prev), [Rx(fp), #offset] + if (aarch64_may_encode_addr_offset(offset + 8, 8)) { + | str Rx(prev), [Rx(fp), #offset] + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset); + | str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)] + } offset += sizeof(void*); } } @@ -1781,15 +1835,22 @@ static void ir_emit_epilogue(ir_ctx *ctx) } if (aarch64_may_encode_imm7_addr_offset(ctx->stack_frame_size+16, 8)) { | ldp x29, x30, [sp], #(ctx->stack_frame_size+16) - } else { + } else if (aarch64_may_encode_imm12(ctx->stack_frame_size+16)) { | ldp x29, x30, [sp] | add sp, sp, #(ctx->stack_frame_size+16) + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size+16); + | ldp x29, x30, [sp] + | add sp, sp, Rx(IR_REG_INT_TMP) } } else if (ctx->stack_frame_size + ctx->call_stack_size) { if (ctx->fixed_stack_red_zone) { IR_ASSERT(ctx->stack_frame_size + ctx->call_stack_size <= ctx->fixed_stack_red_zone); - } else { + } else if (aarch64_may_encode_imm12(ctx->stack_frame_size + ctx->call_stack_size)) { | add sp, sp, #(ctx->stack_frame_size + ctx->call_stack_size) + } else { + ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size + ctx->call_stack_size); + | add sp, sp, Rx(IR_REG_INT_TMP) } } } @@ -4366,11 +4427,15 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; ir_type type = insn->type; - ir_reg def_reg = ctx->regs[def][0]; + ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]); ir_reg op2_reg = ctx->regs[def][2]; ir_reg tmp_reg = ctx->regs[def][3]; int32_t offset; + if (ctx->use_lists[def].count == 1) { + /* dead load */ + return; + } IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { @@ -4394,11 +4459,15 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; ir_type type = insn->type; - ir_reg def_reg = ctx->regs[def][0]; + ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]); ir_reg op2_reg = ctx->regs[def][2]; ir_reg tmp_reg = ctx->regs[def][3]; int32_t offset; + if (ctx->use_lists[def].count == 1) { + /* dead load */ + return; + } IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { @@ -4465,6 +4534,7 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) int count = 0; ir_val min, max; ir_reg op1_reg, op2_reg, tmp_reg; + bool has_case_range = 0; type = ctx->ir_base[insn->op2].type; if (IR_IS_TYPE_SIGNED(type)) { @@ -4493,6 +4563,22 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) max.u64 = (int64_t)IR_MAX(max.u64, val->val.u64); } count++; + } else if (use_insn->op == IR_CASE_RANGE) { + has_case_range = 1; + val = &ctx->ir_base[use_insn->op2]; + IR_ASSERT(!IR_IS_SYM_CONST(val->op)); + ir_insn *val2 = &ctx->ir_base[use_insn->op3]; + IR_ASSERT(!IR_IS_SYM_CONST(val2->op)); + if (IR_IS_TYPE_SIGNED(type)) { + IR_ASSERT(IR_IS_TYPE_SIGNED(val->type)); + min.i64 = IR_MIN(min.i64, val->val.i64); + max.i64 = IR_MAX(max.i64, val2->val.i64); + } else { + IR_ASSERT(!IR_IS_TYPE_SIGNED(val->type)); + min.u64 = (int64_t)IR_MIN(min.u64, val->val.u64); + max.u64 = (int64_t)IR_MAX(max.u64, val2->val.u64); + } + count++; } else { IR_ASSERT(use_insn->op == IR_CASE_DEFAULT); default_label = ir_skip_empty_target_blocks(ctx, use_block); @@ -4510,7 +4596,7 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) } /* Generate a table jmp or a sequence of calls */ - if (count > 2 && (max.i64-min.i64) < count * 8) { + if (!has_case_range && count > 2 && (max.i64-min.i64) < count * 8) { int *labels = ir_mem_malloc(sizeof(int) * (max.i64 - min.i64 + 1)); for (i = 0; i <= (max.i64 - min.i64); i++) { @@ -4615,6 +4701,38 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) } | beq =>label + } else if (use_insn->op == IR_CASE_RANGE) { + val = &ctx->ir_base[use_insn->op2]; + IR_ASSERT(!IR_IS_SYM_CONST(val->op)); + label = ir_skip_empty_target_blocks(ctx, use_block); + if (aarch64_may_encode_imm12(val->val.i64)) { + | ASM_REG_IMM_OP cmp, type, op2_reg, val->val.i64 + } else { + ir_emit_load_imm_int(ctx, type, tmp_reg, val->val.i64); + | ASM_REG_REG_OP cmp, type, op2_reg, tmp_reg + + } + if (IR_IS_TYPE_SIGNED(type)) { + | blt >1 + } else { + | blo >1 + } + val = &ctx->ir_base[use_insn->op3]; + IR_ASSERT(!IR_IS_SYM_CONST(val->op)); + label = ir_skip_empty_target_blocks(ctx, use_block); + if (aarch64_may_encode_imm12(val->val.i64)) { + | ASM_REG_IMM_OP cmp, type, op2_reg, val->val.i64 + } else { + ir_emit_load_imm_int(ctx, type, tmp_reg, val->val.i64); + | ASM_REG_REG_OP cmp, type, op2_reg, tmp_reg + + } + if (IR_IS_TYPE_SIGNED(type)) { + | ble =>label + } else { + | bls =>label + } + |1: } } if (default_label) { @@ -4750,7 +4868,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg fp_param++; } if (dst_reg != IR_REG_NONE) { - if (src_reg == IR_REG_NONE) { + if (IR_IS_CONST_REF(arg) || + src_reg == IR_REG_NONE || + (IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) { /* delay CONST->REG and MEM->REG moves to third pass */ do_pass3 = 1; } else { @@ -4816,7 +4936,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg fp_param++; } if (dst_reg != IR_REG_NONE) { - if (src_reg == IR_REG_NONE) { + if (IR_IS_CONST_REF(arg) || + src_reg == IR_REG_NONE || + (IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) { if (IR_IS_CONST_REF(arg) && IR_IS_TYPE_INT(type)) { if (ir_type_size[type] == 1) { type = IR_ADDR; @@ -4935,6 +5057,28 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) return; } + /* Move op2 to a tmp register before epilogue if it's in + * used_preserved_regs, because it will be overridden. */ + + ir_reg op2_reg = IR_REG_NONE; + if (!IR_IS_CONST_REF(insn->op2)) { + op2_reg = ctx->regs[def][2]; + IR_ASSERT(op2_reg != IR_REG_NONE); + + if (IR_REG_SPILLED(op2_reg)) { + op2_reg = IR_REG_INT_TMP; + ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2); + } else if (IR_REGSET_IN((ir_regset)ctx->used_preserved_regs, IR_REG_NUM(op2_reg))) { + ir_reg orig_op2_reg = op2_reg; + op2_reg = IR_REG_INT_TMP; + + ir_type type = ctx->ir_base[insn->op2].type; + | ASM_REG_REG_OP mov, type, op2_reg, IR_REG_NUM(orig_op2_reg) + } else { + op2_reg = IR_REG_NUM(op2_reg); + } + } + ir_emit_epilogue(ctx); if (IR_IS_CONST_REF(insn->op2)) { @@ -4947,13 +5091,8 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) | br Rx(IR_REG_INT_TMP) } } else { - ir_reg op2_reg = ctx->regs[def][2]; - IR_ASSERT(op2_reg != IR_REG_NONE); - if (IR_REG_SPILLED(op2_reg)) { - op2_reg = IR_REG_NUM(op2_reg); - ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2); - } + IR_ASSERT(!IR_REGSET_IN((ir_regset)ctx->used_preserved_regs, op2_reg)); | br Rx(op2_reg) } } @@ -5398,7 +5537,8 @@ static void ir_emit_load_params(ir_ctx *ctx) int32_t stack_offset = 0; if (ctx->flags & IR_USE_FRAME_POINTER) { - stack_offset = sizeof(void*) * 2; /* skip old frame pointer and return address */ + /* skip old frame pointer and return address */ + stack_offset = sizeof(void*) * 2 + ctx->stack_frame_size + ctx->call_stack_size; } else { stack_offset = ctx->stack_frame_size + ctx->call_stack_size; } @@ -5590,6 +5730,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) case IR_IF_TRUE: case IR_IF_FALSE: case IR_CASE_VAL: + case IR_CASE_RANGE: case IR_CASE_DEFAULT: case IR_MERGE: case IR_LOOP_BEGIN: diff --git a/ext/opcache/jit/ir/ir_aarch64.h b/ext/opcache/jit/ir/ir_aarch64.h index 183d3ec2e1d88..9da64b9249f72 100644 --- a/ext/opcache/jit/ir/ir_aarch64.h +++ b/ext/opcache/jit/ir/ir_aarch64.h @@ -174,8 +174,8 @@ typedef struct _ir_tmp_reg { int8_t reg; }; uint8_t type; - uint8_t start; - uint8_t end; + int8_t start; + int8_t end; } ir_tmp_reg; struct _ir_target_constraints { diff --git a/ext/opcache/jit/ir/ir_builder.h b/ext/opcache/jit/ir/ir_builder.h index 4e4ea53683afb..358ae241e2dd4 100644 --- a/ext/opcache/jit/ir/ir_builder.h +++ b/ext/opcache/jit/ir/ir_builder.h @@ -490,20 +490,20 @@ extern "C" { #define ir_ADD_OFFSET(_addr, _offset) _ir_ADD_OFFSET(_ir_CTX, (_addr), (_offset)) /* Unfoldable variant of COPY */ -#define ir_HARD_COPY(_type, _op1) ir_BINARY_OP(IR_COPY, (_type), (_op1), 1) -#define ir_HARD_COPY_B(_op1) ir_BINARY_OP_B(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_U8(_op1) ir_BINARY_OP_U8(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_U16(_op1) ir_BINARY_OP_U16(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_U32(_op1) ir_BINARY_OP_U32(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_U64(_op1) ir_BINARY_OP_U64(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_A(_op1) ir_BINARY_OP_A(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_C(_op1) ir_BINARY_OP_C(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_I8(_op1) ir_BINARY_OP_I8(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_I16(_op1) ir_BINARY_OP_I16(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_I32(_op1) ir_BINARY_OP_I32(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_I64(_op1) ir_BINARY_OP_I64(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_D(_op1) ir_BINARY_OP_D(IR_COPY, (_op1), 1) -#define ir_HARD_COPY_F(_op1) ir_BINARY_OP_F(IR_COPY, (_op1), 1) +#define ir_HARD_COPY(_type, _op1) ir_emit2(_ir_CTX, IR_OPT(IR_COPY, (_type)), (_op1), 1) +#define ir_HARD_COPY_B(_op1) ir_HARD_COPY(IR_BOOL, _op1) +#define ir_HARD_COPY_U8(_op1) ir_HARD_COPY(IR_U8, _op1) +#define ir_HARD_COPY_U16(_op1) ir_HARD_COPY(IR_U16, _op1) +#define ir_HARD_COPY_U32(_op1) ir_HARD_COPY(IR_U32, _op1) +#define ir_HARD_COPY_U64(_op1) ir_HARD_COPY(IR_U64, _op1) +#define ir_HARD_COPY_A(_op1) ir_HARD_COPY(IR_ADDR, _op1) +#define ir_HARD_COPY_C(_op1) ir_HARD_COPY(IR_CHAR, _op1) +#define ir_HARD_COPY_I8(_op1) ir_HARD_COPY(IR_I8, _op1) +#define ir_HARD_COPY_I16(_op1) ir_HARD_COPY(IR_I16, _op1) +#define ir_HARD_COPY_I32(_op1) ir_HARD_COPY(IR_I32, _op1) +#define ir_HARD_COPY_I64(_op1) ir_HARD_COPY(IR_I64, _op1) +#define ir_HARD_COPY_D(_op1) ir_HARD_COPY(IR_DOUBLE, _op1) +#define ir_HARD_COPY_F(_op1) ir_HARD_COPY(IR_FLOAT, _op1) #define ir_PARAM(_type, _name, _num) _ir_PARAM(_ir_CTX, (_type), (_name), (_num)) #define ir_VAR(_type, _name) _ir_VAR(_ir_CTX, (_type), (_name)) @@ -603,6 +603,7 @@ extern "C" { #define ir_LOOP_END() _ir_LOOP_END(_ir_CTX) #define ir_SWITCH(_val) _ir_SWITCH(_ir_CTX, (_val)) #define ir_CASE_VAL(_switch, _val) _ir_CASE_VAL(_ir_CTX, (_switch), (_val)) +#define ir_CASE_RANGE(_switch, _v1, _v2) _ir_CASE_RANGE(_ir_CTX, (_switch), (_v1), (_v2)) #define ir_CASE_DEFAULT(_switch) _ir_CASE_DEFAULT(_ir_CTX, (_switch)) #define ir_RETURN(_val) _ir_RETURN(_ir_CTX, (_val)) #define ir_IJMP(_addr) _ir_IJMP(_ir_CTX, (_addr)) @@ -682,6 +683,7 @@ ir_ref _ir_TLS(ir_ctx *ctx, ir_ref index, ir_ref offset); void _ir_UNREACHABLE(ir_ctx *ctx); ir_ref _ir_SWITCH(ir_ctx *ctx, ir_ref val); void _ir_CASE_VAL(ir_ctx *ctx, ir_ref switch_ref, ir_ref val); +void _ir_CASE_RANGE(ir_ctx *ctx, ir_ref switch_ref, ir_ref v1, ir_ref v2); void _ir_CASE_DEFAULT(ir_ctx *ctx, ir_ref switch_ref); void _ir_RETURN(ir_ctx *ctx, ir_ref val); void _ir_IJMP(ir_ctx *ctx, ir_ref addr); diff --git a/ext/opcache/jit/ir/ir_cfg.c b/ext/opcache/jit/ir/ir_cfg.c index 01532c8ea3e30..13d66a7130283 100644 --- a/ext/opcache/jit/ir/ir_cfg.c +++ b/ext/opcache/jit/ir/ir_cfg.c @@ -244,7 +244,6 @@ int ir_build_cfg(ir_ctx *ctx) _blocks[start] = b; _blocks[end] = b; IR_ASSERT(IR_IS_BB_START(insn->op)); - IR_ASSERT(end > start); bb->start = start; bb->end = end; bb->successors = count; @@ -583,7 +582,6 @@ static int ir_remove_unreachable_blocks(ir_ctx *ctx) return 1; } -#if 0 static void compute_postnum(const ir_ctx *ctx, uint32_t *cur, uint32_t b) { uint32_t i, *p; @@ -607,34 +605,42 @@ static void compute_postnum(const ir_ctx *ctx, uint32_t *cur, uint32_t b) /* Computes dominator tree using algorithm from "A Simple, Fast Dominance Algorithm" by * Cooper, Harvey and Kennedy. */ -int ir_build_dominators_tree(ir_ctx *ctx) +static int ir_build_dominators_tree_slow(ir_ctx *ctx) { uint32_t blocks_count, b, postnum; ir_block *blocks, *bb; uint32_t *edges; bool changed; + blocks = ctx->cfg_blocks; + edges = ctx->cfg_edges; + blocks_count = ctx->cfg_blocks_count; + + /* Clear the dominators tree */ + for (b = 0, bb = &blocks[0]; b <= blocks_count; b++, bb++) { + bb->idom = 0; + bb->dom_depth = 0; + bb->dom_child = 0; + bb->dom_next_child = 0; + } + ctx->flags2 &= ~IR_NO_LOOPS; postnum = 1; compute_postnum(ctx, &postnum, 1); - /* Find immediate dominators */ - blocks = ctx->cfg_blocks; - edges = ctx->cfg_edges; - blocks_count = ctx->cfg_blocks_count; + /* Find immediate dominators by iterative fixed-point algorithm */ blocks[1].idom = 1; do { changed = 0; /* Iterating in Reverse Post Order */ for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) { IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE)); + IR_ASSERT(bb->predecessors_count > 0); if (bb->predecessors_count == 1) { uint32_t pred_b = edges[bb->predecessors]; - if (blocks[pred_b].idom <= 0) { - //IR_ASSERT("Wrong blocks order: BB is before its single predecessor"); - } else if (bb->idom != pred_b) { + if (blocks[pred_b].idom > 0 && bb->idom != pred_b) { bb->idom = pred_b; changed = 1; } @@ -680,39 +686,53 @@ int ir_build_dominators_tree(ir_ctx *ctx) } } } while (changed); + + /* Build dominators tree */ blocks[1].idom = 0; blocks[1].dom_depth = 0; + for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) { + uint32_t idom = bb->idom; + ir_block *idom_bb = &blocks[idom]; + + bb->dom_depth = 0; + /* Sort by block number to traverse children in pre-order */ + if (idom_bb->dom_child == 0) { + idom_bb->dom_child = b; + } else if (b < idom_bb->dom_child) { + bb->dom_next_child = idom_bb->dom_child; + idom_bb->dom_child = b; + } else { + int child = idom_bb->dom_child; + ir_block *child_bb = &blocks[child]; - /* Construct dominators tree */ + while (child_bb->dom_next_child > 0 && b > child_bb->dom_next_child) { + child = child_bb->dom_next_child; + child_bb = &blocks[child]; + } + bb->dom_next_child = child_bb->dom_next_child; + child_bb->dom_next_child = b; + } + } + + /* Recalculate dom_depth for all blocks */ for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) { - IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE)); - if (bb->idom > 0) { - ir_block *idom_bb = &blocks[bb->idom]; - - bb->dom_depth = idom_bb->dom_depth + 1; - /* Sort by block number to traverse children in pre-order */ - if (idom_bb->dom_child == 0) { - idom_bb->dom_child = b; - } else if (b < idom_bb->dom_child) { - bb->dom_next_child = idom_bb->dom_child; - idom_bb->dom_child = b; + uint32_t idom = bb->idom; + uint32_t dom_depth = 0; + while (idom) { + dom_depth++; + if (blocks[idom].dom_depth > 0) { + dom_depth += blocks[idom].dom_depth; + break; } else { - int child = idom_bb->dom_child; - ir_block *child_bb = &blocks[child]; - - while (child_bb->dom_next_child > 0 && b > child_bb->dom_next_child) { - child = child_bb->dom_next_child; - child_bb = &blocks[child]; - } - bb->dom_next_child = child_bb->dom_next_child; - child_bb->dom_next_child = b; + idom = blocks[idom].idom; } } + bb->dom_depth = dom_depth; } return 1; } -#else + /* A single pass modification of "A Simple, Fast Dominance Algorithm" by * Cooper, Harvey and Kennedy, that relays on IR block ordering. * It may fallback to the general slow fixed-point algorithm. */ @@ -747,7 +767,11 @@ int ir_build_dominators_tree(ir_ctx *ctx) if (UNEXPECTED(idom >= b)) { /* In rare cases, LOOP_BEGIN.op1 may be a back-edge. Skip back-edges. */ ctx->flags2 &= ~IR_NO_LOOPS; - IR_ASSERT(k > 1 && "Wrong blocks order: BB is before its single predecessor"); +// IR_ASSERT(k > 1 && "Wrong blocks order: BB is before its single predecessor"); + if (UNEXPECTED(k <= 1)) { + ir_list_free(&worklist); + return ir_build_dominators_tree_slow(ctx); + } ir_list_push(&worklist, idom); while (1) { k--; @@ -942,7 +966,6 @@ static int ir_build_dominators_tree_iterative(ir_ctx *ctx) return 1; } -#endif static bool ir_dominates(const ir_block *blocks, uint32_t b1, uint32_t b2) { @@ -958,7 +981,7 @@ static bool ir_dominates(const ir_block *blocks, uint32_t b1, uint32_t b2) int ir_find_loops(ir_ctx *ctx) { - uint32_t i, j, n, count; + uint32_t b, j, n, count; uint32_t *entry_times, *exit_times, *sorted_blocks, time = 1; ir_block *blocks = ctx->cfg_blocks; uint32_t *edges = ctx->cfg_edges; @@ -983,13 +1006,13 @@ int ir_find_loops(ir_ctx *ctx) int child; next: - i = ir_worklist_peek(&work); - if (!entry_times[i]) { - entry_times[i] = time++; + b = ir_worklist_peek(&work); + if (!entry_times[b]) { + entry_times[b] = time++; } - /* Visit blocks immediately dominated by i. */ - bb = &blocks[i]; + /* Visit blocks immediately dominated by "b". */ + bb = &blocks[b]; for (child = bb->dom_child; child > 0; child = blocks[child].dom_next_child) { if (ir_worklist_push(&work, child)) { goto next; @@ -999,17 +1022,17 @@ int ir_find_loops(ir_ctx *ctx) /* Visit join edges. */ if (bb->successors_count) { uint32_t *p = edges + bb->successors; - for (j = 0; j < bb->successors_count; j++,p++) { + for (j = 0; j < bb->successors_count; j++, p++) { uint32_t succ = *p; - if (blocks[succ].idom == i) { + if (blocks[succ].idom == b) { continue; } else if (ir_worklist_push(&work, succ)) { goto next; } } } - exit_times[i] = time++; + exit_times[b] = time++; ir_worklist_pop(&work); } @@ -1018,7 +1041,7 @@ int ir_find_loops(ir_ctx *ctx) j = 1; n = 2; while (j != n) { - i = j; + uint32_t i = j; j = n; for (; i < j; i++) { int child; @@ -1030,9 +1053,82 @@ int ir_find_loops(ir_ctx *ctx) count = n; /* Identify loops. See Sreedhar et al, "Identifying Loops Using DJ Graphs". */ + uint32_t prev_dom_depth = blocks[sorted_blocks[n - 1]].dom_depth; + uint32_t prev_irreducible = 0; while (n > 1) { - i = sorted_blocks[--n]; - ir_block *bb = &blocks[i]; + b = sorted_blocks[--n]; + ir_block *bb = &blocks[b]; + + IR_ASSERT(bb->dom_depth <= prev_dom_depth); + if (UNEXPECTED(prev_irreducible) && bb->dom_depth != prev_dom_depth) { + /* process delyed irreducible loops */ + do { + b = sorted_blocks[prev_irreducible]; + bb = &blocks[b]; + if ((bb->flags & IR_BB_IRREDUCIBLE_LOOP) && !bb->loop_depth) { + /* process irreducible loop */ + uint32_t hdr = b; + + bb->loop_depth = 1; + if (ctx->ir_base[bb->start].op == IR_MERGE) { + ctx->ir_base[bb->start].op = IR_LOOP_BEGIN; + } + + /* find the closing edge(s) of the irreucible loop */ + IR_ASSERT(bb->predecessors_count > 1); + uint32_t *p = &edges[bb->predecessors]; + j = bb->predecessors_count; + do { + uint32_t pred = *p; + + if (entry_times[pred] > entry_times[b] && exit_times[pred] < exit_times[b]) { + if (!ir_worklist_len(&work)) { + ir_bitset_clear(work.visited, ir_bitset_len(ir_worklist_capasity(&work))); + } + blocks[pred].loop_header = 0; /* support for merged loops */ + ir_worklist_push(&work, pred); + } + p++; + } while (--j); + if (ir_worklist_len(&work) == 0) continue; + + /* collect members of the irreducible loop */ + while (ir_worklist_len(&work)) { + b = ir_worklist_pop(&work); + if (b != hdr) { + ir_block *bb = &blocks[b]; + bb->loop_header = hdr; + if (bb->predecessors_count) { + uint32_t *p = &edges[bb->predecessors]; + uint32_t n = bb->predecessors_count; + do { + uint32_t pred = *p; + while (blocks[pred].loop_header > 0) { + pred = blocks[pred].loop_header; + } + if (pred != hdr) { + if (entry_times[pred] > entry_times[hdr] && exit_times[pred] < exit_times[hdr]) { + /* "pred" is a descendant of "hdr" */ + ir_worklist_push(&work, pred); + } else { + /* another entry to the irreducible loop */ + bb->flags |= IR_BB_IRREDUCIBLE_LOOP; + if (ctx->ir_base[bb->start].op == IR_MERGE) { + ctx->ir_base[bb->start].op = IR_LOOP_BEGIN; + } + } + } + p++; + } while (--n); + } + } + } + } + } while (--prev_irreducible != n); + prev_irreducible = 0; + b = sorted_blocks[n]; + bb = &blocks[b]; + } if (bb->predecessors_count > 1) { bool irreducible = 0; @@ -1047,7 +1143,7 @@ int ir_find_loops(ir_ctx *ctx) if (bb->idom != pred) { /* In a loop back-edge (back-join edge), the successor dominates the predecessor. */ - if (ir_dominates(blocks, i, pred)) { + if (ir_dominates(blocks, b, pred)) { if (!ir_worklist_len(&work)) { ir_bitset_clear(work.visited, ir_bitset_len(ir_worklist_capasity(&work))); } @@ -1056,8 +1152,9 @@ int ir_find_loops(ir_ctx *ctx) } else { /* Otherwise it's a cross-join edge. See if it's a branch to an ancestor on the DJ spanning tree. */ - if (entry_times[pred] > entry_times[i] && exit_times[pred] < exit_times[i]) { + if (entry_times[pred] > entry_times[b] && exit_times[pred] < exit_times[b]) { irreducible = 1; + break; } } } @@ -1065,46 +1162,56 @@ int ir_find_loops(ir_ctx *ctx) } while (--j); if (UNEXPECTED(irreducible)) { - // TODO: Support for irreducible loops ??? - bb->flags |= IR_BB_IRREDUCIBLE_LOOP; - ctx->flags2 |= IR_IRREDUCIBLE_CFG; - while (ir_worklist_len(&work)) { - ir_worklist_pop(&work); + bb->flags |= IR_BB_LOOP_HEADER | IR_BB_IRREDUCIBLE_LOOP; + ctx->flags2 |= IR_CFG_HAS_LOOPS | IR_IRREDUCIBLE_CFG; + /* Remember the position of the first irreducible loop to process all the irreducible loops + * after the reducible loops with the same dominator tree depth + */ + if (!prev_irreducible) { + prev_irreducible = n; + prev_dom_depth = bb->dom_depth; } + ir_list_clear(&work.l); } else if (ir_worklist_len(&work)) { + /* collect members of the reducible loop */ + uint32_t hdr = b; + bb->flags |= IR_BB_LOOP_HEADER; ctx->flags2 |= IR_CFG_HAS_LOOPS; bb->loop_depth = 1; + if (ctx->ir_base[bb->start].op == IR_MERGE) { + ctx->ir_base[bb->start].op = IR_LOOP_BEGIN; + } while (ir_worklist_len(&work)) { - j = ir_worklist_pop(&work); - while (blocks[j].loop_header > 0) { - j = blocks[j].loop_header; - } - if (j != i) { - ir_block *bb = &blocks[j]; - if (bb->idom == 0 && j != 1) { - /* Ignore blocks that are unreachable or only abnormally reachable. */ - continue; - } - bb->loop_header = i; + b = ir_worklist_pop(&work); + if (b != hdr) { + ir_block *bb = &blocks[b]; + bb->loop_header = hdr; if (bb->predecessors_count) { uint32_t *p = &edges[bb->predecessors]; - j = bb->predecessors_count; + uint32_t n = bb->predecessors_count; do { - ir_worklist_push(&work, *p); + uint32_t pred = *p; + while (blocks[pred].loop_header > 0) { + pred = blocks[pred].loop_header; + } + if (pred != hdr) { + ir_worklist_push(&work, pred); + } p++; - } while (--j); + } while (--n); } } } } } } + IR_ASSERT(!prev_irreducible); if (ctx->flags2 & IR_CFG_HAS_LOOPS) { for (n = 1; n < count; n++) { - i = sorted_blocks[n]; - ir_block *bb = &blocks[i]; + b = sorted_blocks[n]; + ir_block *bb = &blocks[b]; if (bb->loop_header > 0) { ir_block *loop = &blocks[bb->loop_header]; uint32_t loop_depth = loop->loop_depth; @@ -1389,7 +1496,7 @@ static int ir_schedule_blocks_bottom_up(ir_ctx *ctx) goto restart; } } else if (b != predecessor && ctx->cfg_blocks[predecessor].loop_header != b) { - ir_dump_cfg(ctx, stderr); + /* not a loop back-edge */ IR_ASSERT(b == predecessor || ctx->cfg_blocks[predecessor].loop_header == b); } } diff --git a/ext/opcache/jit/ir/ir_check.c b/ext/opcache/jit/ir/ir_check.c index f12b4776fa1e0..a791baef5db92 100644 --- a/ext/opcache/jit/ir/ir_check.c +++ b/ext/opcache/jit/ir/ir_check.c @@ -213,13 +213,18 @@ bool ir_check(const ir_ctx *ctx) ok = 0; } } - break; - case IR_OPND_CONTROL_DEP: if ((ctx->flags2 & IR_LINEAR) && use >= i && !(insn->op == IR_LOOP_BEGIN)) { fprintf(stderr, "ir_base[%d].ops[%d] invalid forward reference (%d)\n", i, j, use); ok = 0; + } + break; + case IR_OPND_CONTROL_DEP: + if ((ctx->flags2 & IR_LINEAR) + && use >= i) { + fprintf(stderr, "ir_base[%d].ops[%d] invalid forward reference (%d)\n", i, j, use); + ok = 0; } else if (insn->op == IR_PHI) { ir_insn *merge_insn = &ctx->ir_base[insn->op1]; if (merge_insn->op != IR_MERGE && merge_insn->op != IR_LOOP_BEGIN) { diff --git a/ext/opcache/jit/ir/ir_emit.c b/ext/opcache/jit/ir/ir_emit.c index c82655daf48db..fab9f56228d80 100644 --- a/ext/opcache/jit/ir/ir_emit.c +++ b/ext/opcache/jit/ir/ir_emit.c @@ -309,7 +309,7 @@ static void* ir_sym_addr(ir_ctx *ctx, const ir_insn *addr_insn) { const char *name = ir_get_str(ctx, addr_insn->val.name); void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? - ctx->loader->resolve_sym_name(ctx->loader, name, 0) : + ctx->loader->resolve_sym_name(ctx->loader, name, IR_RESOLVE_SYM_SILENT) : ir_resolve_sym_name(name); return addr; @@ -320,7 +320,7 @@ static void* ir_sym_val(ir_ctx *ctx, const ir_insn *addr_insn) { const char *name = ir_get_str(ctx, addr_insn->val.name); void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? - ctx->loader->resolve_sym_name(ctx->loader, name, addr_insn->op == IR_FUNC) : + ctx->loader->resolve_sym_name(ctx->loader, name, addr_insn->op == IR_FUNC ? IR_RESOLVE_SYM_ADD_THUNK : 0) : ir_resolve_sym_name(name); IR_ASSERT(addr); diff --git a/ext/opcache/jit/ir/ir_fold.h b/ext/opcache/jit/ir/ir_fold.h index 88539e52ab085..2f5be6ca2e00b 100644 --- a/ext/opcache/jit/ir/ir_fold.h +++ b/ext/opcache/jit/ir/ir_fold.h @@ -924,7 +924,7 @@ IR_FOLD(SHL(C_CHAR, C_CHAR)) IR_FOLD(SHL(C_I8, C_I8)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I(op1_insn->val.i8 << op2_insn->val.i8); + IR_FOLD_CONST_I((int8_t)(op1_insn->val.u8 << op2_insn->val.u8)); } IR_FOLD(SHL(C_U16, C_U16)) @@ -936,7 +936,7 @@ IR_FOLD(SHL(C_U16, C_U16)) IR_FOLD(SHL(C_I16, C_I16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I(op1_insn->val.i16 << op2_insn->val.i16); + IR_FOLD_CONST_I((int16_t)(op1_insn->val.u16 << op2_insn->val.u16)); } IR_FOLD(SHL(C_U32, C_U32)) @@ -948,7 +948,7 @@ IR_FOLD(SHL(C_U32, C_U32)) IR_FOLD(SHL(C_I32, C_I32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_I(op1_insn->val.i32 << op2_insn->val.i32); + IR_FOLD_CONST_I((int32_t)(op1_insn->val.u32 << op2_insn->val.u32)); } IR_FOLD(SHL(C_U64, C_U64)) @@ -980,7 +980,7 @@ IR_FOLD(SHR(C_U16, C_U16)) IR_FOLD(SHR(C_I16, C_I16)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U((int16_t)(op1_insn->val.u16 >> op2_insn->val.u16)); + IR_FOLD_CONST_I((int16_t)(op1_insn->val.u16 >> op2_insn->val.u16)); } IR_FOLD(SHR(C_U32, C_U32)) @@ -992,7 +992,7 @@ IR_FOLD(SHR(C_U32, C_U32)) IR_FOLD(SHR(C_I32, C_I32)) { IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type); - IR_FOLD_CONST_U((int32_t)(op1_insn->val.u32 >> op2_insn->val.u32)); + IR_FOLD_CONST_I((int32_t)(op1_insn->val.u32 >> op2_insn->val.u32)); } IR_FOLD(SHR(C_U64, C_U64)) @@ -1909,7 +1909,9 @@ IR_FOLD(SUB(_, SUB)) IR_FOLD(SUB(ADD, ADD)) { if (IR_IS_TYPE_INT(IR_OPT_TYPE(opt))) { - if (op1_insn->op1 == op2_insn->op1) { + if (op1 == op2) { + IR_FOLD_CONST_U(0); + } else if (op1_insn->op1 == op2_insn->op1) { /* (a + b) - (a + c) => b - c */ op1 = op1_insn->op2; op2 = op2_insn->op2; @@ -2726,7 +2728,7 @@ IR_FOLD(ADD(ADD, C_ADDR)) /* (x + c1) + c2 => x + (c1 + c2) */ val.u64 = ctx->ir_base[op1_insn->op2].val.u64 + op2_insn->val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2741,7 +2743,7 @@ IR_FOLD(ADD(ADD, C_I64)) /* (x + c1) + c2 => x + (c1 + c2) */ val.i64 = ctx->ir_base[op1_insn->op2].val.u64 + op2_insn->val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2757,14 +2759,14 @@ IR_FOLD(ADD(SUB, C_ADDR)) /* (x - c1) + c2 => x + (c2 - c1) */ val.u64 = op2_insn->val.u64 - ctx->ir_base[op1_insn->op2].val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) { /* (c1 - x) + c2 => (c1 + c2) - x */ val.u64 = ctx->ir_base[op1_insn->op1].val.u64 + op2_insn->val.u64; opt++; /* ADD -> SUB */ op2 = op1_insn->op2; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2783,14 +2785,14 @@ IR_FOLD(ADD(SUB, C_I64)) opt++; /* ADD -> SUB */ } op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) { /* (c1 - x) + c2 => (c1 + c2) - x */ val.i64 = ctx->ir_base[op1_insn->op1].val.u64 + op2_insn->val.u64; opt++; /* ADD -> SUB */ op2 = op1_insn->op2; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2807,7 +2809,7 @@ IR_FOLD(SUB(ADD, C_ADDR)) val.u64 = ctx->ir_base[op1_insn->op2].val.u64 - op2_insn->val.u64; opt--; /* SUB -> ADD */ op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2827,7 +2829,7 @@ IR_FOLD(SUB(ADD, C_I64)) opt--; /* SUB -> ADD */ } op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2843,7 +2845,7 @@ IR_FOLD(SUB(C_ADDR, ADD)) /* c1 - (x + c2) => (c1 - c2) - x */ val.u64 = op1_insn->val.u64 - ctx->ir_base[op2_insn->op2].val.u64; op2 = op2_insn->op1; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2858,7 +2860,7 @@ IR_FOLD(SUB(C_I64, ADD)) /* c1 - (x + c2) => (c1 - c2) - x */ val.i64 = op1_insn->val.u64 - ctx->ir_base[op2_insn->op2].val.u64; op2 = op2_insn->op1; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2878,13 +2880,13 @@ IR_FOLD(SUB(SUB, C_ADDR)) opt--; /* SUB -> ADD */ } op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) { /* (c1 - x) - c2 => (c1 - c2) - x */ val.u64 = ctx->ir_base[op1_insn->op1].val.u64 - op2_insn->val.u64; op2 = op1_insn->op2; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2903,13 +2905,13 @@ IR_FOLD(SUB(SUB, C_I64)) opt--; /* SUB -> ADD */ } op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) { /* (c1 - x) - c2 => (c1 - c2) - x */ val.i64 = ctx->ir_base[op1_insn->op1].val.u64 - op2_insn->val.u64; op2 = op1_insn->op2; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2925,7 +2927,7 @@ IR_FOLD(SUB(C_ADDR, SUB)) /* c1 - (x - c2) => (c1 + c2) - x */ val.u64 = op1_insn->val.u64 + ctx->ir_base[op2_insn->op2].val.u64; op2 = op2_insn->op1; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op1_insn->op1); IR_FOLD_RESTART; } else if (IR_IS_CONST_REF(op2_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op1].op)) { /* c1 - (c2 - x) => x + (c1 - c2) */ @@ -2935,7 +2937,7 @@ IR_FOLD(SUB(C_ADDR, SUB)) opt++; /* ADD -> SUB */ } op1 = op2_insn->op2; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op1_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2950,7 +2952,7 @@ IR_FOLD(SUB(C_I64, SUB)) /* c1 - (x - c2) => (c1 + c2) - x */ val.i64 = op1_insn->val.u64 + ctx->ir_base[op2_insn->op2].val.u64; op2 = op2_insn->op1; - op1 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op1 = ir_const(ctx, val, op1_insn->type); IR_FOLD_RESTART; } else if (IR_IS_CONST_REF(op2_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op1].op)) { /* c1 - (c2 - x) => x + (c1 - c2) */ @@ -2960,7 +2962,7 @@ IR_FOLD(SUB(C_I64, SUB)) opt++; /* ADD -> SUB */ } op1 = op2_insn->op2; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op1_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2976,7 +2978,7 @@ IR_FOLD(MUL(MUL, C_ADDR)) /* (x * c1) * c2 => x * (c1 * c2) */ val.u64 = ctx->ir_base[op1_insn->op2].val.u64 * op2_insn->val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -2991,7 +2993,7 @@ IR_FOLD(MUL(MUL, C_I64)) /* (x * c1) * c2 => x * (c1 * c2) */ val.i64 = ctx->ir_base[op1_insn->op2].val.u64 * op2_insn->val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -3011,7 +3013,7 @@ IR_FOLD(AND(AND, C_ADDR)) /* (x & c1) & c2 => x & (c1 & c2) */ val.u64 = ctx->ir_base[op1_insn->op2].val.u64 & op2_insn->val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -3031,7 +3033,7 @@ IR_FOLD(OR(OR, C_ADDR)) /* (x | c1) | c2 => x | (c1 | c2) */ val.u64 = ctx->ir_base[op1_insn->op2].val.u64 | op2_insn->val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; @@ -3051,7 +3053,7 @@ IR_FOLD(XOR(XOR, C_ADDR)) /* (x ^ c1) ^ c2 => x ^ (c1 ^ c2) */ val.u64 = ctx->ir_base[op1_insn->op2].val.u64 ^ op2_insn->val.u64; op1 = op1_insn->op1; - op2 = ir_const(ctx, val, IR_OPT_TYPE(opt)); + op2 = ir_const(ctx, val, op2_insn->type); IR_FOLD_RESTART; } IR_FOLD_NEXT; diff --git a/ext/opcache/jit/ir/ir_gcm.c b/ext/opcache/jit/ir/ir_gcm.c index 8bd6be5d10aa0..3ea78850249ab 100644 --- a/ext/opcache/jit/ir/ir_gcm.c +++ b/ext/opcache/jit/ir/ir_gcm.c @@ -785,6 +785,139 @@ IR_ALWAYS_INLINE ir_ref ir_count_constant(ir_ref *_xlat, ir_ref ref) return 0; } +IR_ALWAYS_INLINE bool ir_is_good_bb_order(ir_ctx *ctx, uint32_t b, ir_block *bb, ir_ref start) +{ + ir_insn *insn = &ctx->ir_base[start]; + uint32_t n = insn->inputs_count; + ir_ref *p = insn->ops + 1; + + if (n == 1) { + return *p < start; + } else { + IR_ASSERT(n > 1); + for (; n > 0; p++, n--) { + ir_ref input = *p; + if (input < start) { + /* ordered */ + } else if ((bb->flags & IR_BB_LOOP_HEADER) + && (ctx->cfg_map[input] == b || ctx->cfg_blocks[ctx->cfg_map[input]].loop_header == b)) { + /* back-edge of reducible loop */ + } else if ((bb->flags & IR_BB_IRREDUCIBLE_LOOP) + && (ctx->cfg_blocks[ctx->cfg_map[input]].loop_header == ctx->cfg_blocks[b].loop_header)) { + /* closing edge of irreducible loop */ + } else { + return 0; + } + } + return 1; + } +} + +static IR_NEVER_INLINE void ir_fix_bb_order(ir_ctx *ctx, ir_ref *_prev, ir_ref *_next) +{ + uint32_t b, succ, count, *q, *xlat; + ir_block *bb; + ir_ref ref, n, prev; + ir_worklist worklist; + ir_block *new_blocks; + +#if 0 + for (b = 1, bb = ctx->cfg_blocks + 1; b <= ctx->cfg_blocks_count; b++, bb++) { + if (!ir_is_good_bb_order(ctx, b, bb, bb->start)) { + goto fix; + } + } + return; + +fix: +#endif + count = ctx->cfg_blocks_count + 1; + new_blocks = ir_mem_malloc(count * sizeof(ir_block)); + xlat = ir_mem_malloc(count * sizeof(uint32_t)); + ir_worklist_init(&worklist, count); + ir_worklist_push(&worklist, 1); + while (ir_worklist_len(&worklist) != 0) { +next: + b = ir_worklist_peek(&worklist); + bb = &ctx->cfg_blocks[b]; + n = bb->successors_count; + if (n == 1) { + succ = ctx->cfg_edges[bb->successors]; + if (ir_worklist_push(&worklist, succ)) { + goto next; + } + } else if (n > 1) { + uint32_t best = 0; + uint32_t best_loop_depth = 0; + + q = ctx->cfg_edges + bb->successors + n; + do { + q--; + succ = *q; + if (ir_bitset_in(worklist.visited, succ)) { + /* already processed */ + } else if ((ctx->cfg_blocks[succ].flags & IR_BB_LOOP_HEADER) + && (succ == b || ctx->cfg_blocks[b].loop_header == succ)) { + /* back-edge of reducible loop */ + } else if ((ctx->cfg_blocks[succ].flags & IR_BB_IRREDUCIBLE_LOOP) + && (ctx->cfg_blocks[succ].loop_header == ctx->cfg_blocks[b].loop_header)) { + /* closing edge of irreducible loop */ + } else if (!best) { + best = succ; + best_loop_depth = ctx->cfg_blocks[best].loop_depth; + } else if (ctx->cfg_blocks[succ].loop_depth < best_loop_depth) { + /* prefer deeper loop */ + best = succ; + best_loop_depth = ctx->cfg_blocks[best].loop_depth; + } + n--; + } while (n > 0); + if (best) { + ir_worklist_push(&worklist, best); + goto next; + } + } + ir_worklist_pop(&worklist); + count--; + new_blocks[count] = *bb; + xlat[b] = count; + } + IR_ASSERT(count == 1); + xlat[0] = 0; + ir_worklist_free(&worklist); + + prev = 0; + for (b = 1, bb = new_blocks + 1; b <= ctx->cfg_blocks_count; b++, bb++) { + bb->idom = xlat[bb->idom]; + bb->loop_header = xlat[bb->loop_header]; + n = bb->successors_count; + if (n > 0) { + for (q = ctx->cfg_edges + bb->successors; n > 0; q++, n--) { + *q = xlat[*q]; + } + } + n = bb->predecessors_count; + if (n > 0) { + for (q = ctx->cfg_edges + bb->predecessors; n > 0; q++, n--) { + *q = xlat[*q]; + } + } + _next[prev] = bb->start; + _prev[bb->start] = prev; + prev = bb->end; + } + _next[0] = 0; + _next[prev] = 0; + + for (ref = 2; ref < ctx->insns_count; ref++) { + ctx->cfg_map[ref] = xlat[ctx->cfg_map[ref]]; + } + ir_mem_free(xlat); + + ir_mem_free(ctx->cfg_blocks); + ctx->cfg_blocks = new_blocks; +} + int ir_schedule(ir_ctx *ctx) { ir_ctx new_ctx; @@ -800,6 +933,7 @@ int ir_schedule(ir_ctx *ctx) ir_block *bb; ir_insn *insn, *new_insn; ir_use_list *lists, *use_list, *new_list; + bool bad_bb_order = 0; /* Create a double-linked list of nodes ordered by BB, respecting BB->start and BB->end */ IR_ASSERT(_blocks[1] == 1); @@ -818,27 +952,61 @@ int ir_schedule(ir_ctx *ctx) } else if (b > prev_b) { bb = &ctx->cfg_blocks[b]; if (i == bb->start) { - IR_ASSERT(bb->end > bb->start); - prev_b = b; - prev_b_end = bb->end; - _prev[bb->end] = 0; - /* add to the end of the list */ - _next[j] = i; - _prev[i] = j; - j = i; - } else { - IR_ASSERT(i != bb->end); + if (bb->end > bb->start) { + prev_b = b; + prev_b_end = bb->end; + /* add to the end of the list */ + _next[j] = i; + _prev[i] = j; + j = i; + } else { + prev_b = 0; + prev_b_end = 0; + k = bb->end; + while (_blocks[_prev[k]] == b) { + k = _prev[k]; + } + /* insert before "k" */ + _prev[i] = _prev[k]; + _next[i] = k; + _next[_prev[k]] = i; + _prev[k] = i; + } + if (!ir_is_good_bb_order(ctx, b, bb, i)) { + bad_bb_order = 1; + } + } else if (i != bb->end) { /* move down late (see the following loop) */ _next[i] = _move_down; _move_down = i; + } else { + prev_b = 0; + prev_b_end = 0; + if (bb->start > bb->end) { + /* add to the end of the list */ + _next[j] = i; + _prev[i] = j; + j = i; + } else { + k = bb->start; + while (_blocks[_next[k]] == b) { + k = _next[k]; + } + /* insert after "k" */ + _next[i] = _next[k]; + _prev[i] = k; + _prev[_next[k]] = i; + _next[k] = i; + } } } else if (b) { bb = &ctx->cfg_blocks[b]; IR_ASSERT(i != bb->start); - if (_prev[bb->end]) { + if (i > bb->end) { /* move up, insert before the end of the already scheduled BB */ k = bb->end; } else { + IR_ASSERT(i > bb->start); /* move up, insert at the end of the block */ k = ctx->cfg_blocks[b + 1].start; } @@ -883,6 +1051,10 @@ int ir_schedule(ir_ctx *ctx) } #endif + if (bad_bb_order) { + ir_fix_bb_order(ctx, _prev, _next); + } + _xlat = ir_mem_calloc((ctx->consts_count + ctx->insns_count), sizeof(ir_ref)); _xlat += ctx->consts_count; _xlat[IR_TRUE] = IR_TRUE; @@ -904,6 +1076,11 @@ int ir_schedule(ir_ctx *ctx) if (insn->op == IR_CASE_VAL) { IR_ASSERT(insn->op2 < IR_TRUE); consts_count += ir_count_constant(_xlat, insn->op2); + } else if (insn->op == IR_CASE_RANGE) { + IR_ASSERT(insn->op2 < IR_TRUE); + consts_count += ir_count_constant(_xlat, insn->op2); + IR_ASSERT(insn->op3 < IR_TRUE); + consts_count += ir_count_constant(_xlat, insn->op3); } n = insn->inputs_count; insns_count += ir_insn_inputs_to_len(n); @@ -1130,14 +1307,17 @@ int ir_schedule(ir_ctx *ctx) new_insn->proto = ir_strl(&new_ctx, proto, len); } } else if (new_insn->op == IR_FUNC) { - new_insn->val.u64 = ir_str(&new_ctx, ir_get_str(ctx, new_insn->val.name)); + size_t len; + const char *name = ir_get_strl(ctx, new_insn->val.name, &len); + new_insn->val.u64 = ir_strl(&new_ctx, name, len); if (new_insn->proto) { - size_t len; const char *proto = ir_get_strl(ctx, new_insn->proto, &len); new_insn->proto = ir_strl(&new_ctx, proto, len); } } else if (new_insn->op == IR_SYM || new_insn->op == IR_STR) { - new_insn->val.u64 = ir_str(&new_ctx, ir_get_str(ctx, new_insn->val.name)); + size_t len; + const char *str = ir_get_strl(ctx, new_insn->val.name, &len); + new_insn->val.u64 = ir_strl(&new_ctx, str, len); } new_insn++; ref++; @@ -1162,16 +1342,19 @@ int ir_schedule(ir_ctx *ctx) new_insn->proto = 0; } } else if (insn->op == IR_FUNC) { - new_insn->val.u64 = ir_str(&new_ctx, ir_get_str(ctx, insn->val.name)); + size_t len; + const char *name = ir_get_strl(ctx, insn->val.name, &len); + new_insn->val.u64 = ir_strl(&new_ctx, name, len); if (insn->proto) { - size_t len; const char *proto = ir_get_strl(ctx, insn->proto, &len); new_insn->proto = ir_strl(&new_ctx, proto, len); } else { new_insn->proto = 0; } } else if (insn->op == IR_SYM || insn->op == IR_STR) { - new_insn->val.u64 = ir_str(&new_ctx, ir_get_str(ctx, insn->val.name)); + size_t len; + const char *str = ir_get_strl(ctx, insn->val.name, &len); + new_insn->val.u64 = ir_strl(&new_ctx, str, len); } else { new_insn->val.u64 = insn->val.u64; } @@ -1236,12 +1419,10 @@ int ir_schedule(ir_ctx *ctx) break; case 1: new_insn->op1 = _xlat[insn->op1]; - if (new_insn->op == IR_PARAM || insn->op == IR_VAR) { - new_insn->op2 = ir_str(&new_ctx, ir_get_str(ctx, insn->op2)); - } else if (new_insn->op == IR_PROTO) { + if (new_insn->op == IR_PARAM || new_insn->op == IR_VAR || new_insn->op == IR_PROTO) { size_t len; - const char *proto = ir_get_strl(ctx, insn->op2, &len); - new_insn->op2 = ir_strl(&new_ctx, proto, len); + const char *str = ir_get_strl(ctx, insn->op2, &len); + new_insn->op2 = ir_strl(&new_ctx, str, len); } else { new_insn->op2 = insn->op2; } diff --git a/ext/opcache/jit/ir/ir_private.h b/ext/opcache/jit/ir/ir_private.h index 69a0101d24ee2..369b4c34e3793 100644 --- a/ext/opcache/jit/ir/ir_private.h +++ b/ext/opcache/jit/ir/ir_private.h @@ -9,6 +9,7 @@ #define IR_PRIVATE_H #include #include +#include #ifdef IR_DEBUG # include @@ -62,7 +63,7 @@ #define IR_MAX(a, b) (((a) > (b)) ? (a) : (b)) #define IR_MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define IR_IS_POWER_OF_TWO(x) (!((x) & ((x) - 1))) +#define IR_IS_POWER_OF_TWO(x) ((x) && (!((x) & ((x) - 1)))) #define IR_LOG2(x) ir_ntzl(x) @@ -257,7 +258,7 @@ IR_ALWAYS_INLINE void* ir_arena_alloc(ir_arena **arena_ptr, size_t size) ir_arena *arena = *arena_ptr; char *ptr = (char*)IR_ALIGNED_SIZE((uintptr_t)arena->ptr, 8); - if (EXPECTED(size <= (size_t)(arena->end - ptr))) { + if (EXPECTED((ptrdiff_t)size <= (ptrdiff_t)(arena->end - ptr))) { arena->ptr = ptr + size; } else { size_t arena_size = diff --git a/ext/opcache/jit/ir/ir_save.c b/ext/opcache/jit/ir/ir_save.c index b12cc267af607..ea787f162ec1f 100644 --- a/ext/opcache/jit/ir/ir_save.c +++ b/ext/opcache/jit/ir/ir_save.c @@ -97,10 +97,14 @@ void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f) for (i = IR_UNUSED + 1, insn = ctx->ir_base - i; i < ctx->consts_count; i++, insn--) { fprintf(f, "\t%s c_%d = ", ir_type_cname[insn->type], i); if (insn->op == IR_FUNC) { - fprintf(f, "func %s", ir_get_str(ctx, insn->val.name)); + fprintf(f, "func %s%s", + (save_flags & IR_SAVE_SAFE_NAMES) ? "@" : "", + ir_get_str(ctx, insn->val.name)); ir_print_proto(ctx, insn->proto, f); } else if (insn->op == IR_SYM) { - fprintf(f, "sym(%s)", ir_get_str(ctx, insn->val.name)); + fprintf(f, "sym(%s%s)", + (save_flags & IR_SAVE_SAFE_NAMES) ? "@" : "", + ir_get_str(ctx, insn->val.name)); } else if (insn->op == IR_FUNC_ADDR) { fprintf(f, "func *"); ir_print_const(ctx, insn, f, true); @@ -140,6 +144,9 @@ void ir_save(const ir_ctx *ctx, uint32_t save_flags, FILE *f) fprintf(f, ", loop=BB%d(%d)", bb->loop_header, bb->loop_depth); } } + if (bb->flags & IR_BB_IRREDUCIBLE_LOOP) { + fprintf(f, ", IRREDUCIBLE"); + } if (bb->predecessors_count) { uint32_t i; diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index 2e006516df818..58de0d726f781 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -458,6 +458,22 @@ static bool ir_sccp_is_equal(ir_ctx *ctx, ir_insn *_values, ir_ref a, ir_ref b) return v1->val.u64 == v2->val.u64; } +static bool ir_sccp_in_range(ir_ctx *ctx, ir_insn *_values, ir_ref a, ir_ref b, ir_ref c) +{ + ir_insn *v1 = IR_IS_CONST_REF(a) ? &ctx->ir_base[a] : &_values[a]; + ir_insn *v2 = IR_IS_CONST_REF(b) ? &ctx->ir_base[b] : &_values[b]; + ir_insn *v3 = IR_IS_CONST_REF(c) ? &ctx->ir_base[c] : &_values[c]; + + IR_ASSERT(!IR_IS_SYM_CONST(v1->op)); + IR_ASSERT(!IR_IS_SYM_CONST(v2->op)); + IR_ASSERT(!IR_IS_SYM_CONST(v3->op)); + if (IR_IS_TYPE_SIGNED(v1->type)) { + return v1->val.i64 >= v2->val.i64 && v1->val.i64 <= v3->val.i64; + } else { + return v1->val.u64 >= v2->val.u64 && v1->val.u64 <= v3->val.u64; + } +} + #ifdef IR_SCCP_TRACE static void ir_sccp_trace_val(ir_ctx *ctx, ir_insn *_values, ir_ref i) { @@ -676,6 +692,11 @@ static IR_NEVER_INLINE void ir_sccp_analyze(ir_ctx *ctx, ir_insn *_values, ir_bi } } else if (use_insn->op == IR_CASE_DEFAULT) { use_case = use; + } else if (use_insn->op == IR_CASE_RANGE) { + if (ir_sccp_in_range(ctx, _values, insn->op2, use_insn->op2, use_insn->op3)) { + use_case = use; + break; + } } } if (use_case) { @@ -1732,7 +1753,20 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use, ir_ref *p, n, input; if (IR_IS_CONST_REF(ref)) { - return ir_const(ctx, insn->val, type); + ir_val val; + + switch (type) { + case IR_I8: val.i64 = insn->val.i8; break; + case IR_U8: val.u64 = insn->val.u8; break; + case IR_I16: val.i64 = insn->val.i16; break; + case IR_U16: val.u64 = insn->val.u16; break; + case IR_I32: val.i64 = insn->val.i32; break; + case IR_U32: val.u64 = insn->val.u32; break; + case IR_CHAR:val.i64 = insn->val.i8; break; + case IR_BOOL:val.u64 = insn->val.u8 != 0; break; + default: IR_ASSERT(0); val.u64 = 0; + } + return ir_const(ctx, val, type); } else { ir_bitqueue_add(worklist, ref); switch (insn->op) { @@ -2391,7 +2425,7 @@ static bool ir_try_remove_empty_diamond(ir_ctx *ctx, ir_ref ref, ir_insn *insn, } start_ref = end->op1; start = &ctx->ir_base[start_ref]; - if (start->op != IR_CASE_VAL && start->op != IR_CASE_DEFAULT) { + if (start->op != IR_CASE_VAL && start->op != IR_CASE_RANGE && start->op != IR_CASE_DEFAULT) { return 0; } if (ctx->use_lists[start_ref].count != 1) { @@ -2961,6 +2995,7 @@ static bool ir_try_split_if(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bitqueue end2->optx = IR_OPTX(IR_IF, IR_VOID, 2); end2->op2 = cond->op3; + ir_bitqueue_add(worklist, end2_ref); merge->optx = IR_OPTX(op, IR_VOID, 1); merge->op1 = end2_ref; @@ -3156,6 +3191,7 @@ static bool ir_try_split_if_cmp(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bitqu end2->optx = IR_OPTX(IR_IF, IR_VOID, 2); end2->op2 = insn->op2; + ir_bitqueue_add(worklist, end2_ref); merge->optx = IR_OPTX(op, IR_VOID, 1); merge->op1 = end2_ref; diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index 76602c2b4bcf5..e5c038fce8e5a 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -1569,6 +1569,20 @@ op2_const: constraints->tmp_regs[0] = IR_TMP_REG(1, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); n = 1; break; + case IR_SSE_SQRT: + case IR_SSE_RINT: + case IR_SSE_FLOOR: + case IR_SSE_CEIL: + case IR_SSE_TRUNC: + case IR_SSE_NEARBYINT: + insn = &ctx->ir_base[ref]; + flags = IR_USE_MUST_BE_IN_REG | IR_OP3_MUST_BE_IN_REG; + if (IR_IS_CONST_REF(insn->op3)) { + const ir_insn *val_insn = &ctx->ir_base[insn->op3]; + constraints->tmp_regs[n] = IR_TMP_REG(3, val_insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF); + n = 1; + } + break; } constraints->tmps_count = n; @@ -2630,6 +2644,7 @@ store_int: case IR_IF_TRUE: case IR_IF_FALSE: case IR_CASE_VAL: + case IR_CASE_RANGE: case IR_CASE_DEFAULT: case IR_MERGE: case IR_LOOP_BEGIN: @@ -6868,7 +6883,24 @@ static void ir_emit_return_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn) ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; - if (op2_reg == IR_REG_NONE || IR_REG_SPILLED(op2_reg)) { + if (IR_IS_CONST_REF(insn->op2)) { + ir_insn *value = &ctx->ir_base[insn->op2]; + + if ((type == IR_FLOAT && value->val.f == 0.0) || (type == IR_DOUBLE && value->val.d == 0.0)) { + | fldz + } else if ((type == IR_FLOAT && value->val.f == 1.0) || (type == IR_DOUBLE && value->val.d == 1.0)) { + | fld1 + } else { + int label = ir_const_label(ctx, insn->op2); + + if (type == IR_DOUBLE) { + | fld qword [=>label] + } else { + IR_ASSERT(type == IR_FLOAT); + | fld dword [=>label] + } + } + } else if (op2_reg == IR_REG_NONE || IR_REG_SPILLED(op2_reg)) { ir_reg fp; int32_t offset = ir_ref_spill_slot_offset(ctx, insn->op2, &fp); @@ -8442,11 +8474,15 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; ir_type type = insn->type; - ir_reg def_reg = ctx->regs[def][0]; + ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]); ir_reg op2_reg = ctx->regs[def][2]; ir_reg tmp_reg = ctx->regs[def][3]; int32_t offset; + if (ctx->use_lists[def].count == 1) { + /* dead load */ + return; + } IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { @@ -8471,11 +8507,15 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn) ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; ir_type type = insn->type; - ir_reg def_reg = ctx->regs[def][0]; + ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]); ir_reg op2_reg = ctx->regs[def][2]; ir_reg tmp_reg = ctx->regs[def][3]; int32_t offset; + if (ctx->use_lists[def].count == 1) { + /* dead load */ + return; + } IR_ASSERT(def_reg != IR_REG_NONE&& tmp_reg != IR_REG_NONE); if (op2_reg != IR_REG_NONE) { if (IR_REG_SPILLED(op2_reg)) { @@ -8541,6 +8581,7 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) ir_val min, max; ir_reg op2_reg = ctx->regs[def][2]; ir_reg tmp_reg = ctx->regs[def][3]; + bool has_case_range = 0; type = ctx->ir_base[insn->op2].type; IR_ASSERT(tmp_reg != IR_REG_NONE); @@ -8570,6 +8611,21 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) max.u64 = (int64_t)IR_MAX(max.u64, val->val.u64); } count++; + } else if (use_insn->op == IR_CASE_RANGE) { + has_case_range = 1; + val = &ctx->ir_base[use_insn->op2]; + IR_ASSERT(!IR_IS_SYM_CONST(val->op)); + ir_insn *val2 = &ctx->ir_base[use_insn->op3]; + IR_ASSERT(!IR_IS_SYM_CONST(val2->op)); + if (IR_IS_TYPE_SIGNED(type)) { + IR_ASSERT(IR_IS_TYPE_SIGNED(val->type)); + min.i64 = IR_MIN(min.i64, val->val.i64); + max.i64 = IR_MAX(max.i64, val2->val.i64); + } else { + IR_ASSERT(!IR_IS_TYPE_SIGNED(val->type)); + min.u64 = (int64_t)IR_MIN(min.u64, val->val.u64); + max.u64 = (int64_t)IR_MAX(max.u64, val2->val.u64); + } } else { IR_ASSERT(use_insn->op == IR_CASE_DEFAULT); default_label = ir_skip_empty_target_blocks(ctx, use_block); @@ -8583,7 +8639,7 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) } /* Generate a table jmp or a seqence of calls */ - if (count > 2 && (max.i64-min.i64) < count * 8) { + if (!has_case_range && count > 2 && (max.i64-min.i64) < count * 8) { int *labels = ir_mem_malloc(sizeof(int) * (size_t)(max.i64 - min.i64 + 1)); for (i = 0; i <= (max.i64 - min.i64); i++) { @@ -8747,6 +8803,42 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn) |.endif } | je =>label + } else if (use_insn->op == IR_CASE_RANGE) { + val = &ctx->ir_base[use_insn->op2]; + IR_ASSERT(!IR_IS_SYM_CONST(val->op)); + label = ir_skip_empty_target_blocks(ctx, use_block); + if (IR_IS_32BIT(type, val->val)) { + | ASM_REG_IMM_OP cmp, type, op2_reg, val->val.i32 + } else { + IR_ASSERT(sizeof(void*) == 8); +|.if X64 + | mov64 Ra(tmp_reg), val->val.i64 + | ASM_REG_REG_OP cmp, type, op2_reg, tmp_reg +|.endif + } + if (IR_IS_TYPE_SIGNED(type)) { + | jl >1 + } else { + | jb >1 + } + val = &ctx->ir_base[use_insn->op3]; + IR_ASSERT(!IR_IS_SYM_CONST(val->op3)); + label = ir_skip_empty_target_blocks(ctx, use_block); + if (IR_IS_32BIT(type, val->val)) { + | ASM_REG_IMM_OP cmp, type, op2_reg, val->val.i32 + } else { + IR_ASSERT(sizeof(void*) == 8); +|.if X64 + | mov64 Ra(tmp_reg), val->val.i64 + | ASM_REG_REG_OP cmp, type, op2_reg, tmp_reg +|.endif + } + if (IR_IS_TYPE_SIGNED(type)) { + | jle =>label + } else { + | jbe =>label + } + |1: } } if (default_label) { @@ -8908,7 +9000,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg #endif } if (dst_reg != IR_REG_NONE) { - if (src_reg == IR_REG_NONE) { + if (IR_IS_CONST_REF(arg) || + src_reg == IR_REG_NONE || + (IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) { /* delay CONST->REG and MEM->REG moves to third pass */ do_pass3 = 1; } else { @@ -8976,7 +9070,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg #endif } if (dst_reg != IR_REG_NONE) { - if (src_reg == IR_REG_NONE) { + if (IR_IS_CONST_REF(arg) || + src_reg == IR_REG_NONE || + (IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) { if (IR_IS_TYPE_INT(type)) { if (IR_IS_CONST_REF(arg)) { if (type == IR_I8 || type == IR_I16) { @@ -9221,6 +9317,58 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) return; } + /* Move op2 to a tmp register before epilogue if it's in + * used_preserved_regs, because it will be overridden. */ + + ir_reg op2_reg = IR_REG_NONE; + ir_mem mem = IR_MEM_B(IR_REG_NONE); + if (!IR_IS_CONST_REF(insn->op2)) { + op2_reg = ctx->regs[def][2]; + + ir_regset preserved_regs = (ir_regset)ctx->used_preserved_regs | IR_REGSET(IR_REG_STACK_POINTER); + if (ctx->flags & IR_USE_FRAME_POINTER) { + preserved_regs |= IR_REGSET(IR_REG_FRAME_POINTER); + } + + bool is_spill_slot = op2_reg != IR_REG_NONE + && IR_REG_SPILLED(op2_reg) + && ctx->vregs[insn->op2]; + + if (op2_reg != IR_REG_NONE && !is_spill_slot) { + if (IR_REGSET_IN(preserved_regs, IR_REG_NUM(op2_reg))) { + ir_ref orig_op2_reg = op2_reg; + op2_reg = IR_REG_RAX; + + if (IR_REG_SPILLED(orig_op2_reg)) { + ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2); + } else { + ir_type type = ctx->ir_base[insn->op2].type; + | ASM_REG_REG_OP mov, type, op2_reg, IR_REG_NUM(orig_op2_reg) + } + } else { + op2_reg = IR_REG_NUM(op2_reg); + } + } else { + if (ir_rule(ctx, insn->op2) & IR_FUSED) { + IR_ASSERT(op2_reg == IR_REG_NONE); + mem = ir_fuse_load(ctx, def, insn->op2); + } else { + mem = ir_ref_spill_slot(ctx, insn->op2); + } + ir_reg base = IR_MEM_BASE(mem); + ir_reg index = IR_MEM_INDEX(mem); + if ((base != IR_REG_NONE && IR_REGSET_IN(preserved_regs, base)) || + (index != IR_REG_NONE && IR_REGSET_IN(preserved_regs, index))) { + op2_reg = IR_REG_RAX; + + ir_type type = ctx->ir_base[insn->op2].type; + ir_emit_load_mem_int(ctx, type, op2_reg, mem); + } else { + op2_reg = IR_REG_NONE; + } + } + } + ir_emit_epilogue(ctx); if (IR_IS_CONST_REF(insn->op2)) { @@ -9246,22 +9394,10 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) |.endif } } else { - ir_reg op2_reg = ctx->regs[def][2]; - if (op2_reg != IR_REG_NONE) { - if (IR_REG_SPILLED(op2_reg)) { - op2_reg = IR_REG_NUM(op2_reg); - ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2); - } + IR_ASSERT(!IR_REGSET_IN((ir_regset)ctx->used_preserved_regs, op2_reg)); | jmp Ra(op2_reg) } else { - ir_mem mem; - - if (ir_rule(ctx, insn->op2) & IR_FUSED) { - mem = ir_fuse_load(ctx, def, insn->op2); - } else { - mem = ir_ref_spill_slot(ctx, insn->op2); - } | ASM_TMEM_OP jmp, aword, mem } } @@ -10314,6 +10450,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) case IR_IF_TRUE: case IR_IF_FALSE: case IR_CASE_VAL: + case IR_CASE_RANGE: case IR_CASE_DEFAULT: case IR_MERGE: case IR_LOOP_BEGIN: diff --git a/ext/opcache/jit/ir/ir_x86.h b/ext/opcache/jit/ir/ir_x86.h index 4b86c291bdfc6..06bfa951cf21d 100644 --- a/ext/opcache/jit/ir/ir_x86.h +++ b/ext/opcache/jit/ir/ir_x86.h @@ -218,8 +218,8 @@ typedef struct _ir_tmp_reg { int8_t reg; }; uint8_t type; - uint8_t start; - uint8_t end; + int8_t start; + int8_t end; } ir_tmp_reg; struct _ir_target_constraints { diff --git a/ext/opcache/jit/tls/testing/.gitignore b/ext/opcache/jit/tls/testing/.gitignore new file mode 100644 index 0000000000000..3873646140f91 --- /dev/null +++ b/ext/opcache/jit/tls/testing/.gitignore @@ -0,0 +1,4 @@ +*.so +*.o +main +main.dSYM diff --git a/ext/opcache/jit/tls/testing/def-vars.h b/ext/opcache/jit/tls/testing/def-vars.h new file mode 100644 index 0000000000000..66cdc2442b8cd --- /dev/null +++ b/ext/opcache/jit/tls/testing/def-vars.h @@ -0,0 +1,1030 @@ +/* Declare a few additional TLS variables to fill any surplus space, + * so _tsrm_ls_cache is allocated in the dynamic section. */ + +#define DEF_VAR(prefix, num) __thread void* prefix##num +#define DEF_VARS(prefix) \ + DEF_VAR(prefix, 0000); \ + DEF_VAR(prefix, 0001); \ + DEF_VAR(prefix, 0002); \ + DEF_VAR(prefix, 0003); \ + DEF_VAR(prefix, 0004); \ + DEF_VAR(prefix, 0005); \ + DEF_VAR(prefix, 0006); \ + DEF_VAR(prefix, 0007); \ + DEF_VAR(prefix, 0008); \ + DEF_VAR(prefix, 0009); \ + DEF_VAR(prefix, 0010); \ + DEF_VAR(prefix, 0011); \ + DEF_VAR(prefix, 0012); \ + DEF_VAR(prefix, 0013); \ + DEF_VAR(prefix, 0014); \ + DEF_VAR(prefix, 0015); \ + DEF_VAR(prefix, 0016); \ + DEF_VAR(prefix, 0017); \ + DEF_VAR(prefix, 0018); \ + DEF_VAR(prefix, 0019); \ + DEF_VAR(prefix, 0020); \ + DEF_VAR(prefix, 0021); \ + DEF_VAR(prefix, 0022); \ + DEF_VAR(prefix, 0023); \ + DEF_VAR(prefix, 0024); \ + DEF_VAR(prefix, 0025); \ + DEF_VAR(prefix, 0026); \ + DEF_VAR(prefix, 0027); \ + DEF_VAR(prefix, 0028); \ + DEF_VAR(prefix, 0029); \ + DEF_VAR(prefix, 0030); \ + DEF_VAR(prefix, 0031); \ + DEF_VAR(prefix, 0032); \ + DEF_VAR(prefix, 0033); \ + DEF_VAR(prefix, 0034); \ + DEF_VAR(prefix, 0035); \ + DEF_VAR(prefix, 0036); \ + DEF_VAR(prefix, 0037); \ + DEF_VAR(prefix, 0038); \ + DEF_VAR(prefix, 0039); \ + DEF_VAR(prefix, 0040); \ + DEF_VAR(prefix, 0041); \ + DEF_VAR(prefix, 0042); \ + DEF_VAR(prefix, 0043); \ + DEF_VAR(prefix, 0044); \ + DEF_VAR(prefix, 0045); \ + DEF_VAR(prefix, 0046); \ + DEF_VAR(prefix, 0047); \ + DEF_VAR(prefix, 0048); \ + DEF_VAR(prefix, 0049); \ + DEF_VAR(prefix, 0050); \ + DEF_VAR(prefix, 0051); \ + DEF_VAR(prefix, 0052); \ + DEF_VAR(prefix, 0053); \ + DEF_VAR(prefix, 0054); \ + DEF_VAR(prefix, 0055); \ + DEF_VAR(prefix, 0056); \ + DEF_VAR(prefix, 0057); \ + DEF_VAR(prefix, 0058); \ + DEF_VAR(prefix, 0059); \ + DEF_VAR(prefix, 0060); \ + DEF_VAR(prefix, 0061); \ + DEF_VAR(prefix, 0062); \ + DEF_VAR(prefix, 0063); \ + DEF_VAR(prefix, 0064); \ + DEF_VAR(prefix, 0065); \ + DEF_VAR(prefix, 0066); \ + DEF_VAR(prefix, 0067); \ + DEF_VAR(prefix, 0068); \ + DEF_VAR(prefix, 0069); \ + DEF_VAR(prefix, 0070); \ + DEF_VAR(prefix, 0071); \ + DEF_VAR(prefix, 0072); \ + DEF_VAR(prefix, 0073); \ + DEF_VAR(prefix, 0074); \ + DEF_VAR(prefix, 0075); \ + DEF_VAR(prefix, 0076); \ + DEF_VAR(prefix, 0077); \ + DEF_VAR(prefix, 0078); \ + DEF_VAR(prefix, 0079); \ + DEF_VAR(prefix, 0080); \ + DEF_VAR(prefix, 0081); \ + DEF_VAR(prefix, 0082); \ + DEF_VAR(prefix, 0083); \ + DEF_VAR(prefix, 0084); \ + DEF_VAR(prefix, 0085); \ + DEF_VAR(prefix, 0086); \ + DEF_VAR(prefix, 0087); \ + DEF_VAR(prefix, 0088); \ + DEF_VAR(prefix, 0089); \ + DEF_VAR(prefix, 0090); \ + DEF_VAR(prefix, 0091); \ + DEF_VAR(prefix, 0092); \ + DEF_VAR(prefix, 0093); \ + DEF_VAR(prefix, 0094); \ + DEF_VAR(prefix, 0095); \ + DEF_VAR(prefix, 0096); \ + DEF_VAR(prefix, 0097); \ + DEF_VAR(prefix, 0098); \ + DEF_VAR(prefix, 0099); \ + DEF_VAR(prefix, 0100); \ + DEF_VAR(prefix, 0101); \ + DEF_VAR(prefix, 0102); \ + DEF_VAR(prefix, 0103); \ + DEF_VAR(prefix, 0104); \ + DEF_VAR(prefix, 0105); \ + DEF_VAR(prefix, 0106); \ + DEF_VAR(prefix, 0107); \ + DEF_VAR(prefix, 0108); \ + DEF_VAR(prefix, 0109); \ + DEF_VAR(prefix, 0110); \ + DEF_VAR(prefix, 0111); \ + DEF_VAR(prefix, 0112); \ + DEF_VAR(prefix, 0113); \ + DEF_VAR(prefix, 0114); \ + DEF_VAR(prefix, 0115); \ + DEF_VAR(prefix, 0116); \ + DEF_VAR(prefix, 0117); \ + DEF_VAR(prefix, 0118); \ + DEF_VAR(prefix, 0119); \ + DEF_VAR(prefix, 0120); \ + DEF_VAR(prefix, 0121); \ + DEF_VAR(prefix, 0122); \ + DEF_VAR(prefix, 0123); \ + DEF_VAR(prefix, 0124); \ + DEF_VAR(prefix, 0125); \ + DEF_VAR(prefix, 0126); \ + DEF_VAR(prefix, 0127); \ + DEF_VAR(prefix, 0128); \ + DEF_VAR(prefix, 0129); \ + DEF_VAR(prefix, 0130); \ + DEF_VAR(prefix, 0131); \ + DEF_VAR(prefix, 0132); \ + DEF_VAR(prefix, 0133); \ + DEF_VAR(prefix, 0134); \ + DEF_VAR(prefix, 0135); \ + DEF_VAR(prefix, 0136); \ + DEF_VAR(prefix, 0137); \ + DEF_VAR(prefix, 0138); \ + DEF_VAR(prefix, 0139); \ + DEF_VAR(prefix, 0140); \ + DEF_VAR(prefix, 0141); \ + DEF_VAR(prefix, 0142); \ + DEF_VAR(prefix, 0143); \ + DEF_VAR(prefix, 0144); \ + DEF_VAR(prefix, 0145); \ + DEF_VAR(prefix, 0146); \ + DEF_VAR(prefix, 0147); \ + DEF_VAR(prefix, 0148); \ + DEF_VAR(prefix, 0149); \ + DEF_VAR(prefix, 0150); \ + DEF_VAR(prefix, 0151); \ + DEF_VAR(prefix, 0152); \ + DEF_VAR(prefix, 0153); \ + DEF_VAR(prefix, 0154); \ + DEF_VAR(prefix, 0155); \ + DEF_VAR(prefix, 0156); \ + DEF_VAR(prefix, 0157); \ + DEF_VAR(prefix, 0158); \ + DEF_VAR(prefix, 0159); \ + DEF_VAR(prefix, 0160); \ + DEF_VAR(prefix, 0161); \ + DEF_VAR(prefix, 0162); \ + DEF_VAR(prefix, 0163); \ + DEF_VAR(prefix, 0164); \ + DEF_VAR(prefix, 0165); \ + DEF_VAR(prefix, 0166); \ + DEF_VAR(prefix, 0167); \ + DEF_VAR(prefix, 0168); \ + DEF_VAR(prefix, 0169); \ + DEF_VAR(prefix, 0170); \ + DEF_VAR(prefix, 0171); \ + DEF_VAR(prefix, 0172); \ + DEF_VAR(prefix, 0173); \ + DEF_VAR(prefix, 0174); \ + DEF_VAR(prefix, 0175); \ + DEF_VAR(prefix, 0176); \ + DEF_VAR(prefix, 0177); \ + DEF_VAR(prefix, 0178); \ + DEF_VAR(prefix, 0179); \ + DEF_VAR(prefix, 0180); \ + DEF_VAR(prefix, 0181); \ + DEF_VAR(prefix, 0182); \ + DEF_VAR(prefix, 0183); \ + DEF_VAR(prefix, 0184); \ + DEF_VAR(prefix, 0185); \ + DEF_VAR(prefix, 0186); \ + DEF_VAR(prefix, 0187); \ + DEF_VAR(prefix, 0188); \ + DEF_VAR(prefix, 0189); \ + DEF_VAR(prefix, 0190); \ + DEF_VAR(prefix, 0191); \ + DEF_VAR(prefix, 0192); \ + DEF_VAR(prefix, 0193); \ + DEF_VAR(prefix, 0194); \ + DEF_VAR(prefix, 0195); \ + DEF_VAR(prefix, 0196); \ + DEF_VAR(prefix, 0197); \ + DEF_VAR(prefix, 0198); \ + DEF_VAR(prefix, 0199); \ + DEF_VAR(prefix, 0200); \ + DEF_VAR(prefix, 0201); \ + DEF_VAR(prefix, 0202); \ + DEF_VAR(prefix, 0203); \ + DEF_VAR(prefix, 0204); \ + DEF_VAR(prefix, 0205); \ + DEF_VAR(prefix, 0206); \ + DEF_VAR(prefix, 0207); \ + DEF_VAR(prefix, 0208); \ + DEF_VAR(prefix, 0209); \ + DEF_VAR(prefix, 0210); \ + DEF_VAR(prefix, 0211); \ + DEF_VAR(prefix, 0212); \ + DEF_VAR(prefix, 0213); \ + DEF_VAR(prefix, 0214); \ + DEF_VAR(prefix, 0215); \ + DEF_VAR(prefix, 0216); \ + DEF_VAR(prefix, 0217); \ + DEF_VAR(prefix, 0218); \ + DEF_VAR(prefix, 0219); \ + DEF_VAR(prefix, 0220); \ + DEF_VAR(prefix, 0221); \ + DEF_VAR(prefix, 0222); \ + DEF_VAR(prefix, 0223); \ + DEF_VAR(prefix, 0224); \ + DEF_VAR(prefix, 0225); \ + DEF_VAR(prefix, 0226); \ + DEF_VAR(prefix, 0227); \ + DEF_VAR(prefix, 0228); \ + DEF_VAR(prefix, 0229); \ + DEF_VAR(prefix, 0230); \ + DEF_VAR(prefix, 0231); \ + DEF_VAR(prefix, 0232); \ + DEF_VAR(prefix, 0233); \ + DEF_VAR(prefix, 0234); \ + DEF_VAR(prefix, 0235); \ + DEF_VAR(prefix, 0236); \ + DEF_VAR(prefix, 0237); \ + DEF_VAR(prefix, 0238); \ + DEF_VAR(prefix, 0239); \ + DEF_VAR(prefix, 0240); \ + DEF_VAR(prefix, 0241); \ + DEF_VAR(prefix, 0242); \ + DEF_VAR(prefix, 0243); \ + DEF_VAR(prefix, 0244); \ + DEF_VAR(prefix, 0245); \ + DEF_VAR(prefix, 0246); \ + DEF_VAR(prefix, 0247); \ + DEF_VAR(prefix, 0248); \ + DEF_VAR(prefix, 0249); \ + DEF_VAR(prefix, 0250); \ + DEF_VAR(prefix, 0251); \ + DEF_VAR(prefix, 0252); \ + DEF_VAR(prefix, 0253); \ + DEF_VAR(prefix, 0254); \ + DEF_VAR(prefix, 0255); \ + DEF_VAR(prefix, 0256); \ + DEF_VAR(prefix, 0257); \ + DEF_VAR(prefix, 0258); \ + DEF_VAR(prefix, 0259); \ + DEF_VAR(prefix, 0260); \ + DEF_VAR(prefix, 0261); \ + DEF_VAR(prefix, 0262); \ + DEF_VAR(prefix, 0263); \ + DEF_VAR(prefix, 0264); \ + DEF_VAR(prefix, 0265); \ + DEF_VAR(prefix, 0266); \ + DEF_VAR(prefix, 0267); \ + DEF_VAR(prefix, 0268); \ + DEF_VAR(prefix, 0269); \ + DEF_VAR(prefix, 0270); \ + DEF_VAR(prefix, 0271); \ + DEF_VAR(prefix, 0272); \ + DEF_VAR(prefix, 0273); \ + DEF_VAR(prefix, 0274); \ + DEF_VAR(prefix, 0275); \ + DEF_VAR(prefix, 0276); \ + DEF_VAR(prefix, 0277); \ + DEF_VAR(prefix, 0278); \ + DEF_VAR(prefix, 0279); \ + DEF_VAR(prefix, 0280); \ + DEF_VAR(prefix, 0281); \ + DEF_VAR(prefix, 0282); \ + DEF_VAR(prefix, 0283); \ + DEF_VAR(prefix, 0284); \ + DEF_VAR(prefix, 0285); \ + DEF_VAR(prefix, 0286); \ + DEF_VAR(prefix, 0287); \ + DEF_VAR(prefix, 0288); \ + DEF_VAR(prefix, 0289); \ + DEF_VAR(prefix, 0290); \ + DEF_VAR(prefix, 0291); \ + DEF_VAR(prefix, 0292); \ + DEF_VAR(prefix, 0293); \ + DEF_VAR(prefix, 0294); \ + DEF_VAR(prefix, 0295); \ + DEF_VAR(prefix, 0296); \ + DEF_VAR(prefix, 0297); \ + DEF_VAR(prefix, 0298); \ + DEF_VAR(prefix, 0299); \ + DEF_VAR(prefix, 0300); \ + DEF_VAR(prefix, 0301); \ + DEF_VAR(prefix, 0302); \ + DEF_VAR(prefix, 0303); \ + DEF_VAR(prefix, 0304); \ + DEF_VAR(prefix, 0305); \ + DEF_VAR(prefix, 0306); \ + DEF_VAR(prefix, 0307); \ + DEF_VAR(prefix, 0308); \ + DEF_VAR(prefix, 0309); \ + DEF_VAR(prefix, 0310); \ + DEF_VAR(prefix, 0311); \ + DEF_VAR(prefix, 0312); \ + DEF_VAR(prefix, 0313); \ + DEF_VAR(prefix, 0314); \ + DEF_VAR(prefix, 0315); \ + DEF_VAR(prefix, 0316); \ + DEF_VAR(prefix, 0317); \ + DEF_VAR(prefix, 0318); \ + DEF_VAR(prefix, 0319); \ + DEF_VAR(prefix, 0320); \ + DEF_VAR(prefix, 0321); \ + DEF_VAR(prefix, 0322); \ + DEF_VAR(prefix, 0323); \ + DEF_VAR(prefix, 0324); \ + DEF_VAR(prefix, 0325); \ + DEF_VAR(prefix, 0326); \ + DEF_VAR(prefix, 0327); \ + DEF_VAR(prefix, 0328); \ + DEF_VAR(prefix, 0329); \ + DEF_VAR(prefix, 0330); \ + DEF_VAR(prefix, 0331); \ + DEF_VAR(prefix, 0332); \ + DEF_VAR(prefix, 0333); \ + DEF_VAR(prefix, 0334); \ + DEF_VAR(prefix, 0335); \ + DEF_VAR(prefix, 0336); \ + DEF_VAR(prefix, 0337); \ + DEF_VAR(prefix, 0338); \ + DEF_VAR(prefix, 0339); \ + DEF_VAR(prefix, 0340); \ + DEF_VAR(prefix, 0341); \ + DEF_VAR(prefix, 0342); \ + DEF_VAR(prefix, 0343); \ + DEF_VAR(prefix, 0344); \ + DEF_VAR(prefix, 0345); \ + DEF_VAR(prefix, 0346); \ + DEF_VAR(prefix, 0347); \ + DEF_VAR(prefix, 0348); \ + DEF_VAR(prefix, 0349); \ + DEF_VAR(prefix, 0350); \ + DEF_VAR(prefix, 0351); \ + DEF_VAR(prefix, 0352); \ + DEF_VAR(prefix, 0353); \ + DEF_VAR(prefix, 0354); \ + DEF_VAR(prefix, 0355); \ + DEF_VAR(prefix, 0356); \ + DEF_VAR(prefix, 0357); \ + DEF_VAR(prefix, 0358); \ + DEF_VAR(prefix, 0359); \ + DEF_VAR(prefix, 0360); \ + DEF_VAR(prefix, 0361); \ + DEF_VAR(prefix, 0362); \ + DEF_VAR(prefix, 0363); \ + DEF_VAR(prefix, 0364); \ + DEF_VAR(prefix, 0365); \ + DEF_VAR(prefix, 0366); \ + DEF_VAR(prefix, 0367); \ + DEF_VAR(prefix, 0368); \ + DEF_VAR(prefix, 0369); \ + DEF_VAR(prefix, 0370); \ + DEF_VAR(prefix, 0371); \ + DEF_VAR(prefix, 0372); \ + DEF_VAR(prefix, 0373); \ + DEF_VAR(prefix, 0374); \ + DEF_VAR(prefix, 0375); \ + DEF_VAR(prefix, 0376); \ + DEF_VAR(prefix, 0377); \ + DEF_VAR(prefix, 0378); \ + DEF_VAR(prefix, 0379); \ + DEF_VAR(prefix, 0380); \ + DEF_VAR(prefix, 0381); \ + DEF_VAR(prefix, 0382); \ + DEF_VAR(prefix, 0383); \ + DEF_VAR(prefix, 0384); \ + DEF_VAR(prefix, 0385); \ + DEF_VAR(prefix, 0386); \ + DEF_VAR(prefix, 0387); \ + DEF_VAR(prefix, 0388); \ + DEF_VAR(prefix, 0389); \ + DEF_VAR(prefix, 0390); \ + DEF_VAR(prefix, 0391); \ + DEF_VAR(prefix, 0392); \ + DEF_VAR(prefix, 0393); \ + DEF_VAR(prefix, 0394); \ + DEF_VAR(prefix, 0395); \ + DEF_VAR(prefix, 0396); \ + DEF_VAR(prefix, 0397); \ + DEF_VAR(prefix, 0398); \ + DEF_VAR(prefix, 0399); \ + DEF_VAR(prefix, 0400); \ + DEF_VAR(prefix, 0401); \ + DEF_VAR(prefix, 0402); \ + DEF_VAR(prefix, 0403); \ + DEF_VAR(prefix, 0404); \ + DEF_VAR(prefix, 0405); \ + DEF_VAR(prefix, 0406); \ + DEF_VAR(prefix, 0407); \ + DEF_VAR(prefix, 0408); \ + DEF_VAR(prefix, 0409); \ + DEF_VAR(prefix, 0410); \ + DEF_VAR(prefix, 0411); \ + DEF_VAR(prefix, 0412); \ + DEF_VAR(prefix, 0413); \ + DEF_VAR(prefix, 0414); \ + DEF_VAR(prefix, 0415); \ + DEF_VAR(prefix, 0416); \ + DEF_VAR(prefix, 0417); \ + DEF_VAR(prefix, 0418); \ + DEF_VAR(prefix, 0419); \ + DEF_VAR(prefix, 0420); \ + DEF_VAR(prefix, 0421); \ + DEF_VAR(prefix, 0422); \ + DEF_VAR(prefix, 0423); \ + DEF_VAR(prefix, 0424); \ + DEF_VAR(prefix, 0425); \ + DEF_VAR(prefix, 0426); \ + DEF_VAR(prefix, 0427); \ + DEF_VAR(prefix, 0428); \ + DEF_VAR(prefix, 0429); \ + DEF_VAR(prefix, 0430); \ + DEF_VAR(prefix, 0431); \ + DEF_VAR(prefix, 0432); \ + DEF_VAR(prefix, 0433); \ + DEF_VAR(prefix, 0434); \ + DEF_VAR(prefix, 0435); \ + DEF_VAR(prefix, 0436); \ + DEF_VAR(prefix, 0437); \ + DEF_VAR(prefix, 0438); \ + DEF_VAR(prefix, 0439); \ + DEF_VAR(prefix, 0440); \ + DEF_VAR(prefix, 0441); \ + DEF_VAR(prefix, 0442); \ + DEF_VAR(prefix, 0443); \ + DEF_VAR(prefix, 0444); \ + DEF_VAR(prefix, 0445); \ + DEF_VAR(prefix, 0446); \ + DEF_VAR(prefix, 0447); \ + DEF_VAR(prefix, 0448); \ + DEF_VAR(prefix, 0449); \ + DEF_VAR(prefix, 0450); \ + DEF_VAR(prefix, 0451); \ + DEF_VAR(prefix, 0452); \ + DEF_VAR(prefix, 0453); \ + DEF_VAR(prefix, 0454); \ + DEF_VAR(prefix, 0455); \ + DEF_VAR(prefix, 0456); \ + DEF_VAR(prefix, 0457); \ + DEF_VAR(prefix, 0458); \ + DEF_VAR(prefix, 0459); \ + DEF_VAR(prefix, 0460); \ + DEF_VAR(prefix, 0461); \ + DEF_VAR(prefix, 0462); \ + DEF_VAR(prefix, 0463); \ + DEF_VAR(prefix, 0464); \ + DEF_VAR(prefix, 0465); \ + DEF_VAR(prefix, 0466); \ + DEF_VAR(prefix, 0467); \ + DEF_VAR(prefix, 0468); \ + DEF_VAR(prefix, 0469); \ + DEF_VAR(prefix, 0470); \ + DEF_VAR(prefix, 0471); \ + DEF_VAR(prefix, 0472); \ + DEF_VAR(prefix, 0473); \ + DEF_VAR(prefix, 0474); \ + DEF_VAR(prefix, 0475); \ + DEF_VAR(prefix, 0476); \ + DEF_VAR(prefix, 0477); \ + DEF_VAR(prefix, 0478); \ + DEF_VAR(prefix, 0479); \ + DEF_VAR(prefix, 0480); \ + DEF_VAR(prefix, 0481); \ + DEF_VAR(prefix, 0482); \ + DEF_VAR(prefix, 0483); \ + DEF_VAR(prefix, 0484); \ + DEF_VAR(prefix, 0485); \ + DEF_VAR(prefix, 0486); \ + DEF_VAR(prefix, 0487); \ + DEF_VAR(prefix, 0488); \ + DEF_VAR(prefix, 0489); \ + DEF_VAR(prefix, 0490); \ + DEF_VAR(prefix, 0491); \ + DEF_VAR(prefix, 0492); \ + DEF_VAR(prefix, 0493); \ + DEF_VAR(prefix, 0494); \ + DEF_VAR(prefix, 0495); \ + DEF_VAR(prefix, 0496); \ + DEF_VAR(prefix, 0497); \ + DEF_VAR(prefix, 0498); \ + DEF_VAR(prefix, 0499); \ + DEF_VAR(prefix, 0500); \ + DEF_VAR(prefix, 0501); \ + DEF_VAR(prefix, 0502); \ + DEF_VAR(prefix, 0503); \ + DEF_VAR(prefix, 0504); \ + DEF_VAR(prefix, 0505); \ + DEF_VAR(prefix, 0506); \ + DEF_VAR(prefix, 0507); \ + DEF_VAR(prefix, 0508); \ + DEF_VAR(prefix, 0509); \ + DEF_VAR(prefix, 0510); \ + DEF_VAR(prefix, 0511); \ + DEF_VAR(prefix, 0512); \ + DEF_VAR(prefix, 0513); \ + DEF_VAR(prefix, 0514); \ + DEF_VAR(prefix, 0515); \ + DEF_VAR(prefix, 0516); \ + DEF_VAR(prefix, 0517); \ + DEF_VAR(prefix, 0518); \ + DEF_VAR(prefix, 0519); \ + DEF_VAR(prefix, 0520); \ + DEF_VAR(prefix, 0521); \ + DEF_VAR(prefix, 0522); \ + DEF_VAR(prefix, 0523); \ + DEF_VAR(prefix, 0524); \ + DEF_VAR(prefix, 0525); \ + DEF_VAR(prefix, 0526); \ + DEF_VAR(prefix, 0527); \ + DEF_VAR(prefix, 0528); \ + DEF_VAR(prefix, 0529); \ + DEF_VAR(prefix, 0530); \ + DEF_VAR(prefix, 0531); \ + DEF_VAR(prefix, 0532); \ + DEF_VAR(prefix, 0533); \ + DEF_VAR(prefix, 0534); \ + DEF_VAR(prefix, 0535); \ + DEF_VAR(prefix, 0536); \ + DEF_VAR(prefix, 0537); \ + DEF_VAR(prefix, 0538); \ + DEF_VAR(prefix, 0539); \ + DEF_VAR(prefix, 0540); \ + DEF_VAR(prefix, 0541); \ + DEF_VAR(prefix, 0542); \ + DEF_VAR(prefix, 0543); \ + DEF_VAR(prefix, 0544); \ + DEF_VAR(prefix, 0545); \ + DEF_VAR(prefix, 0546); \ + DEF_VAR(prefix, 0547); \ + DEF_VAR(prefix, 0548); \ + DEF_VAR(prefix, 0549); \ + DEF_VAR(prefix, 0550); \ + DEF_VAR(prefix, 0551); \ + DEF_VAR(prefix, 0552); \ + DEF_VAR(prefix, 0553); \ + DEF_VAR(prefix, 0554); \ + DEF_VAR(prefix, 0555); \ + DEF_VAR(prefix, 0556); \ + DEF_VAR(prefix, 0557); \ + DEF_VAR(prefix, 0558); \ + DEF_VAR(prefix, 0559); \ + DEF_VAR(prefix, 0560); \ + DEF_VAR(prefix, 0561); \ + DEF_VAR(prefix, 0562); \ + DEF_VAR(prefix, 0563); \ + DEF_VAR(prefix, 0564); \ + DEF_VAR(prefix, 0565); \ + DEF_VAR(prefix, 0566); \ + DEF_VAR(prefix, 0567); \ + DEF_VAR(prefix, 0568); \ + DEF_VAR(prefix, 0569); \ + DEF_VAR(prefix, 0570); \ + DEF_VAR(prefix, 0571); \ + DEF_VAR(prefix, 0572); \ + DEF_VAR(prefix, 0573); \ + DEF_VAR(prefix, 0574); \ + DEF_VAR(prefix, 0575); \ + DEF_VAR(prefix, 0576); \ + DEF_VAR(prefix, 0577); \ + DEF_VAR(prefix, 0578); \ + DEF_VAR(prefix, 0579); \ + DEF_VAR(prefix, 0580); \ + DEF_VAR(prefix, 0581); \ + DEF_VAR(prefix, 0582); \ + DEF_VAR(prefix, 0583); \ + DEF_VAR(prefix, 0584); \ + DEF_VAR(prefix, 0585); \ + DEF_VAR(prefix, 0586); \ + DEF_VAR(prefix, 0587); \ + DEF_VAR(prefix, 0588); \ + DEF_VAR(prefix, 0589); \ + DEF_VAR(prefix, 0590); \ + DEF_VAR(prefix, 0591); \ + DEF_VAR(prefix, 0592); \ + DEF_VAR(prefix, 0593); \ + DEF_VAR(prefix, 0594); \ + DEF_VAR(prefix, 0595); \ + DEF_VAR(prefix, 0596); \ + DEF_VAR(prefix, 0597); \ + DEF_VAR(prefix, 0598); \ + DEF_VAR(prefix, 0599); \ + DEF_VAR(prefix, 0600); \ + DEF_VAR(prefix, 0601); \ + DEF_VAR(prefix, 0602); \ + DEF_VAR(prefix, 0603); \ + DEF_VAR(prefix, 0604); \ + DEF_VAR(prefix, 0605); \ + DEF_VAR(prefix, 0606); \ + DEF_VAR(prefix, 0607); \ + DEF_VAR(prefix, 0608); \ + DEF_VAR(prefix, 0609); \ + DEF_VAR(prefix, 0610); \ + DEF_VAR(prefix, 0611); \ + DEF_VAR(prefix, 0612); \ + DEF_VAR(prefix, 0613); \ + DEF_VAR(prefix, 0614); \ + DEF_VAR(prefix, 0615); \ + DEF_VAR(prefix, 0616); \ + DEF_VAR(prefix, 0617); \ + DEF_VAR(prefix, 0618); \ + DEF_VAR(prefix, 0619); \ + DEF_VAR(prefix, 0620); \ + DEF_VAR(prefix, 0621); \ + DEF_VAR(prefix, 0622); \ + DEF_VAR(prefix, 0623); \ + DEF_VAR(prefix, 0624); \ + DEF_VAR(prefix, 0625); \ + DEF_VAR(prefix, 0626); \ + DEF_VAR(prefix, 0627); \ + DEF_VAR(prefix, 0628); \ + DEF_VAR(prefix, 0629); \ + DEF_VAR(prefix, 0630); \ + DEF_VAR(prefix, 0631); \ + DEF_VAR(prefix, 0632); \ + DEF_VAR(prefix, 0633); \ + DEF_VAR(prefix, 0634); \ + DEF_VAR(prefix, 0635); \ + DEF_VAR(prefix, 0636); \ + DEF_VAR(prefix, 0637); \ + DEF_VAR(prefix, 0638); \ + DEF_VAR(prefix, 0639); \ + DEF_VAR(prefix, 0640); \ + DEF_VAR(prefix, 0641); \ + DEF_VAR(prefix, 0642); \ + DEF_VAR(prefix, 0643); \ + DEF_VAR(prefix, 0644); \ + DEF_VAR(prefix, 0645); \ + DEF_VAR(prefix, 0646); \ + DEF_VAR(prefix, 0647); \ + DEF_VAR(prefix, 0648); \ + DEF_VAR(prefix, 0649); \ + DEF_VAR(prefix, 0650); \ + DEF_VAR(prefix, 0651); \ + DEF_VAR(prefix, 0652); \ + DEF_VAR(prefix, 0653); \ + DEF_VAR(prefix, 0654); \ + DEF_VAR(prefix, 0655); \ + DEF_VAR(prefix, 0656); \ + DEF_VAR(prefix, 0657); \ + DEF_VAR(prefix, 0658); \ + DEF_VAR(prefix, 0659); \ + DEF_VAR(prefix, 0660); \ + DEF_VAR(prefix, 0661); \ + DEF_VAR(prefix, 0662); \ + DEF_VAR(prefix, 0663); \ + DEF_VAR(prefix, 0664); \ + DEF_VAR(prefix, 0665); \ + DEF_VAR(prefix, 0666); \ + DEF_VAR(prefix, 0667); \ + DEF_VAR(prefix, 0668); \ + DEF_VAR(prefix, 0669); \ + DEF_VAR(prefix, 0670); \ + DEF_VAR(prefix, 0671); \ + DEF_VAR(prefix, 0672); \ + DEF_VAR(prefix, 0673); \ + DEF_VAR(prefix, 0674); \ + DEF_VAR(prefix, 0675); \ + DEF_VAR(prefix, 0676); \ + DEF_VAR(prefix, 0677); \ + DEF_VAR(prefix, 0678); \ + DEF_VAR(prefix, 0679); \ + DEF_VAR(prefix, 0680); \ + DEF_VAR(prefix, 0681); \ + DEF_VAR(prefix, 0682); \ + DEF_VAR(prefix, 0683); \ + DEF_VAR(prefix, 0684); \ + DEF_VAR(prefix, 0685); \ + DEF_VAR(prefix, 0686); \ + DEF_VAR(prefix, 0687); \ + DEF_VAR(prefix, 0688); \ + DEF_VAR(prefix, 0689); \ + DEF_VAR(prefix, 0690); \ + DEF_VAR(prefix, 0691); \ + DEF_VAR(prefix, 0692); \ + DEF_VAR(prefix, 0693); \ + DEF_VAR(prefix, 0694); \ + DEF_VAR(prefix, 0695); \ + DEF_VAR(prefix, 0696); \ + DEF_VAR(prefix, 0697); \ + DEF_VAR(prefix, 0698); \ + DEF_VAR(prefix, 0699); \ + DEF_VAR(prefix, 0700); \ + DEF_VAR(prefix, 0701); \ + DEF_VAR(prefix, 0702); \ + DEF_VAR(prefix, 0703); \ + DEF_VAR(prefix, 0704); \ + DEF_VAR(prefix, 0705); \ + DEF_VAR(prefix, 0706); \ + DEF_VAR(prefix, 0707); \ + DEF_VAR(prefix, 0708); \ + DEF_VAR(prefix, 0709); \ + DEF_VAR(prefix, 0710); \ + DEF_VAR(prefix, 0711); \ + DEF_VAR(prefix, 0712); \ + DEF_VAR(prefix, 0713); \ + DEF_VAR(prefix, 0714); \ + DEF_VAR(prefix, 0715); \ + DEF_VAR(prefix, 0716); \ + DEF_VAR(prefix, 0717); \ + DEF_VAR(prefix, 0718); \ + DEF_VAR(prefix, 0719); \ + DEF_VAR(prefix, 0720); \ + DEF_VAR(prefix, 0721); \ + DEF_VAR(prefix, 0722); \ + DEF_VAR(prefix, 0723); \ + DEF_VAR(prefix, 0724); \ + DEF_VAR(prefix, 0725); \ + DEF_VAR(prefix, 0726); \ + DEF_VAR(prefix, 0727); \ + DEF_VAR(prefix, 0728); \ + DEF_VAR(prefix, 0729); \ + DEF_VAR(prefix, 0730); \ + DEF_VAR(prefix, 0731); \ + DEF_VAR(prefix, 0732); \ + DEF_VAR(prefix, 0733); \ + DEF_VAR(prefix, 0734); \ + DEF_VAR(prefix, 0735); \ + DEF_VAR(prefix, 0736); \ + DEF_VAR(prefix, 0737); \ + DEF_VAR(prefix, 0738); \ + DEF_VAR(prefix, 0739); \ + DEF_VAR(prefix, 0740); \ + DEF_VAR(prefix, 0741); \ + DEF_VAR(prefix, 0742); \ + DEF_VAR(prefix, 0743); \ + DEF_VAR(prefix, 0744); \ + DEF_VAR(prefix, 0745); \ + DEF_VAR(prefix, 0746); \ + DEF_VAR(prefix, 0747); \ + DEF_VAR(prefix, 0748); \ + DEF_VAR(prefix, 0749); \ + DEF_VAR(prefix, 0750); \ + DEF_VAR(prefix, 0751); \ + DEF_VAR(prefix, 0752); \ + DEF_VAR(prefix, 0753); \ + DEF_VAR(prefix, 0754); \ + DEF_VAR(prefix, 0755); \ + DEF_VAR(prefix, 0756); \ + DEF_VAR(prefix, 0757); \ + DEF_VAR(prefix, 0758); \ + DEF_VAR(prefix, 0759); \ + DEF_VAR(prefix, 0760); \ + DEF_VAR(prefix, 0761); \ + DEF_VAR(prefix, 0762); \ + DEF_VAR(prefix, 0763); \ + DEF_VAR(prefix, 0764); \ + DEF_VAR(prefix, 0765); \ + DEF_VAR(prefix, 0766); \ + DEF_VAR(prefix, 0767); \ + DEF_VAR(prefix, 0768); \ + DEF_VAR(prefix, 0769); \ + DEF_VAR(prefix, 0770); \ + DEF_VAR(prefix, 0771); \ + DEF_VAR(prefix, 0772); \ + DEF_VAR(prefix, 0773); \ + DEF_VAR(prefix, 0774); \ + DEF_VAR(prefix, 0775); \ + DEF_VAR(prefix, 0776); \ + DEF_VAR(prefix, 0777); \ + DEF_VAR(prefix, 0778); \ + DEF_VAR(prefix, 0779); \ + DEF_VAR(prefix, 0780); \ + DEF_VAR(prefix, 0781); \ + DEF_VAR(prefix, 0782); \ + DEF_VAR(prefix, 0783); \ + DEF_VAR(prefix, 0784); \ + DEF_VAR(prefix, 0785); \ + DEF_VAR(prefix, 0786); \ + DEF_VAR(prefix, 0787); \ + DEF_VAR(prefix, 0788); \ + DEF_VAR(prefix, 0789); \ + DEF_VAR(prefix, 0790); \ + DEF_VAR(prefix, 0791); \ + DEF_VAR(prefix, 0792); \ + DEF_VAR(prefix, 0793); \ + DEF_VAR(prefix, 0794); \ + DEF_VAR(prefix, 0795); \ + DEF_VAR(prefix, 0796); \ + DEF_VAR(prefix, 0797); \ + DEF_VAR(prefix, 0798); \ + DEF_VAR(prefix, 0799); \ + DEF_VAR(prefix, 0800); \ + DEF_VAR(prefix, 0801); \ + DEF_VAR(prefix, 0802); \ + DEF_VAR(prefix, 0803); \ + DEF_VAR(prefix, 0804); \ + DEF_VAR(prefix, 0805); \ + DEF_VAR(prefix, 0806); \ + DEF_VAR(prefix, 0807); \ + DEF_VAR(prefix, 0808); \ + DEF_VAR(prefix, 0809); \ + DEF_VAR(prefix, 0810); \ + DEF_VAR(prefix, 0811); \ + DEF_VAR(prefix, 0812); \ + DEF_VAR(prefix, 0813); \ + DEF_VAR(prefix, 0814); \ + DEF_VAR(prefix, 0815); \ + DEF_VAR(prefix, 0816); \ + DEF_VAR(prefix, 0817); \ + DEF_VAR(prefix, 0818); \ + DEF_VAR(prefix, 0819); \ + DEF_VAR(prefix, 0820); \ + DEF_VAR(prefix, 0821); \ + DEF_VAR(prefix, 0822); \ + DEF_VAR(prefix, 0823); \ + DEF_VAR(prefix, 0824); \ + DEF_VAR(prefix, 0825); \ + DEF_VAR(prefix, 0826); \ + DEF_VAR(prefix, 0827); \ + DEF_VAR(prefix, 0828); \ + DEF_VAR(prefix, 0829); \ + DEF_VAR(prefix, 0830); \ + DEF_VAR(prefix, 0831); \ + DEF_VAR(prefix, 0832); \ + DEF_VAR(prefix, 0833); \ + DEF_VAR(prefix, 0834); \ + DEF_VAR(prefix, 0835); \ + DEF_VAR(prefix, 0836); \ + DEF_VAR(prefix, 0837); \ + DEF_VAR(prefix, 0838); \ + DEF_VAR(prefix, 0839); \ + DEF_VAR(prefix, 0840); \ + DEF_VAR(prefix, 0841); \ + DEF_VAR(prefix, 0842); \ + DEF_VAR(prefix, 0843); \ + DEF_VAR(prefix, 0844); \ + DEF_VAR(prefix, 0845); \ + DEF_VAR(prefix, 0846); \ + DEF_VAR(prefix, 0847); \ + DEF_VAR(prefix, 0848); \ + DEF_VAR(prefix, 0849); \ + DEF_VAR(prefix, 0850); \ + DEF_VAR(prefix, 0851); \ + DEF_VAR(prefix, 0852); \ + DEF_VAR(prefix, 0853); \ + DEF_VAR(prefix, 0854); \ + DEF_VAR(prefix, 0855); \ + DEF_VAR(prefix, 0856); \ + DEF_VAR(prefix, 0857); \ + DEF_VAR(prefix, 0858); \ + DEF_VAR(prefix, 0859); \ + DEF_VAR(prefix, 0860); \ + DEF_VAR(prefix, 0861); \ + DEF_VAR(prefix, 0862); \ + DEF_VAR(prefix, 0863); \ + DEF_VAR(prefix, 0864); \ + DEF_VAR(prefix, 0865); \ + DEF_VAR(prefix, 0866); \ + DEF_VAR(prefix, 0867); \ + DEF_VAR(prefix, 0868); \ + DEF_VAR(prefix, 0869); \ + DEF_VAR(prefix, 0870); \ + DEF_VAR(prefix, 0871); \ + DEF_VAR(prefix, 0872); \ + DEF_VAR(prefix, 0873); \ + DEF_VAR(prefix, 0874); \ + DEF_VAR(prefix, 0875); \ + DEF_VAR(prefix, 0876); \ + DEF_VAR(prefix, 0877); \ + DEF_VAR(prefix, 0878); \ + DEF_VAR(prefix, 0879); \ + DEF_VAR(prefix, 0880); \ + DEF_VAR(prefix, 0881); \ + DEF_VAR(prefix, 0882); \ + DEF_VAR(prefix, 0883); \ + DEF_VAR(prefix, 0884); \ + DEF_VAR(prefix, 0885); \ + DEF_VAR(prefix, 0886); \ + DEF_VAR(prefix, 0887); \ + DEF_VAR(prefix, 0888); \ + DEF_VAR(prefix, 0889); \ + DEF_VAR(prefix, 0890); \ + DEF_VAR(prefix, 0891); \ + DEF_VAR(prefix, 0892); \ + DEF_VAR(prefix, 0893); \ + DEF_VAR(prefix, 0894); \ + DEF_VAR(prefix, 0895); \ + DEF_VAR(prefix, 0896); \ + DEF_VAR(prefix, 0897); \ + DEF_VAR(prefix, 0898); \ + DEF_VAR(prefix, 0899); \ + DEF_VAR(prefix, 0900); \ + DEF_VAR(prefix, 0901); \ + DEF_VAR(prefix, 0902); \ + DEF_VAR(prefix, 0903); \ + DEF_VAR(prefix, 0904); \ + DEF_VAR(prefix, 0905); \ + DEF_VAR(prefix, 0906); \ + DEF_VAR(prefix, 0907); \ + DEF_VAR(prefix, 0908); \ + DEF_VAR(prefix, 0909); \ + DEF_VAR(prefix, 0910); \ + DEF_VAR(prefix, 0911); \ + DEF_VAR(prefix, 0912); \ + DEF_VAR(prefix, 0913); \ + DEF_VAR(prefix, 0914); \ + DEF_VAR(prefix, 0915); \ + DEF_VAR(prefix, 0916); \ + DEF_VAR(prefix, 0917); \ + DEF_VAR(prefix, 0918); \ + DEF_VAR(prefix, 0919); \ + DEF_VAR(prefix, 0920); \ + DEF_VAR(prefix, 0921); \ + DEF_VAR(prefix, 0922); \ + DEF_VAR(prefix, 0923); \ + DEF_VAR(prefix, 0924); \ + DEF_VAR(prefix, 0925); \ + DEF_VAR(prefix, 0926); \ + DEF_VAR(prefix, 0927); \ + DEF_VAR(prefix, 0928); \ + DEF_VAR(prefix, 0929); \ + DEF_VAR(prefix, 0930); \ + DEF_VAR(prefix, 0931); \ + DEF_VAR(prefix, 0932); \ + DEF_VAR(prefix, 0933); \ + DEF_VAR(prefix, 0934); \ + DEF_VAR(prefix, 0935); \ + DEF_VAR(prefix, 0936); \ + DEF_VAR(prefix, 0937); \ + DEF_VAR(prefix, 0938); \ + DEF_VAR(prefix, 0939); \ + DEF_VAR(prefix, 0940); \ + DEF_VAR(prefix, 0941); \ + DEF_VAR(prefix, 0942); \ + DEF_VAR(prefix, 0943); \ + DEF_VAR(prefix, 0944); \ + DEF_VAR(prefix, 0945); \ + DEF_VAR(prefix, 0946); \ + DEF_VAR(prefix, 0947); \ + DEF_VAR(prefix, 0948); \ + DEF_VAR(prefix, 0949); \ + DEF_VAR(prefix, 0950); \ + DEF_VAR(prefix, 0951); \ + DEF_VAR(prefix, 0952); \ + DEF_VAR(prefix, 0953); \ + DEF_VAR(prefix, 0954); \ + DEF_VAR(prefix, 0955); \ + DEF_VAR(prefix, 0956); \ + DEF_VAR(prefix, 0957); \ + DEF_VAR(prefix, 0958); \ + DEF_VAR(prefix, 0959); \ + DEF_VAR(prefix, 0960); \ + DEF_VAR(prefix, 0961); \ + DEF_VAR(prefix, 0962); \ + DEF_VAR(prefix, 0963); \ + DEF_VAR(prefix, 0964); \ + DEF_VAR(prefix, 0965); \ + DEF_VAR(prefix, 0966); \ + DEF_VAR(prefix, 0967); \ + DEF_VAR(prefix, 0968); \ + DEF_VAR(prefix, 0969); \ + DEF_VAR(prefix, 0970); \ + DEF_VAR(prefix, 0971); \ + DEF_VAR(prefix, 0972); \ + DEF_VAR(prefix, 0973); \ + DEF_VAR(prefix, 0974); \ + DEF_VAR(prefix, 0975); \ + DEF_VAR(prefix, 0976); \ + DEF_VAR(prefix, 0977); \ + DEF_VAR(prefix, 0978); \ + DEF_VAR(prefix, 0979); \ + DEF_VAR(prefix, 0980); \ + DEF_VAR(prefix, 0981); \ + DEF_VAR(prefix, 0982); \ + DEF_VAR(prefix, 0983); \ + DEF_VAR(prefix, 0984); \ + DEF_VAR(prefix, 0985); \ + DEF_VAR(prefix, 0986); \ + DEF_VAR(prefix, 0987); \ + DEF_VAR(prefix, 0988); \ + DEF_VAR(prefix, 0989); \ + DEF_VAR(prefix, 0990); \ + DEF_VAR(prefix, 0991); \ + DEF_VAR(prefix, 0992); \ + DEF_VAR(prefix, 0993); \ + DEF_VAR(prefix, 0994); \ + DEF_VAR(prefix, 0995); \ + DEF_VAR(prefix, 0996); \ + DEF_VAR(prefix, 0997); \ + DEF_VAR(prefix, 0998); \ + DEF_VAR(prefix, 0999); \ + DEF_VAR(prefix, 1000); \ + DEF_VAR(prefix, 1001); \ + DEF_VAR(prefix, 1002); \ + DEF_VAR(prefix, 1003); \ + DEF_VAR(prefix, 1004); \ + DEF_VAR(prefix, 1005); \ + DEF_VAR(prefix, 1006); \ + DEF_VAR(prefix, 1007); \ + DEF_VAR(prefix, 1008); \ + DEF_VAR(prefix, 1009); \ + DEF_VAR(prefix, 1010); \ + DEF_VAR(prefix, 1011); \ + DEF_VAR(prefix, 1012); \ + DEF_VAR(prefix, 1013); \ + DEF_VAR(prefix, 1014); \ + DEF_VAR(prefix, 1015); \ + DEF_VAR(prefix, 1016); \ + DEF_VAR(prefix, 1017); \ + DEF_VAR(prefix, 1018); \ + DEF_VAR(prefix, 1019); \ + DEF_VAR(prefix, 1020); \ + DEF_VAR(prefix, 1021); \ + DEF_VAR(prefix, 1022); \ + DEF_VAR(prefix, 1023); \ + DEF_VAR(prefix, 1024); diff --git a/ext/opcache/jit/tls/testing/def.c b/ext/opcache/jit/tls/testing/def.c new file mode 100644 index 0000000000000..f18d577e278a5 --- /dev/null +++ b/ext/opcache/jit/tls/testing/def.c @@ -0,0 +1,33 @@ + +/* _tsrm_ls_cache is defined here */ + +#include +#include +#include + +#ifdef NO_SURPLUS +# include "def-vars.h" +DEF_VARS(def); +#endif + +__thread void* _tsrm_ls_cache; + +size_t tsrm_get_ls_cache_tcb_offset(void) { + return 0; +} + +void zend_accel_error(int type, const char *format, ...) { + if (type < 4) { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + } +} + +int test(void); + +int decl(void) { + return test(); +} + diff --git a/ext/opcache/jit/tls/testing/main.c b/ext/opcache/jit/tls/testing/main.c new file mode 100644 index 0000000000000..75d40ff7888ea --- /dev/null +++ b/ext/opcache/jit/tls/testing/main.c @@ -0,0 +1,48 @@ +#include +#include + +#ifdef NO_SURPLUS +# include "def-vars.h" +DEF_VARS(main); +#endif + +__thread int some_tls_var; + +#ifndef DL_DECL +int decl(void); +#endif + +int main(void) { + /* Ensure TLS vars are allocated */ + some_tls_var = 1; + + int (*decl_p)(void); +#ifdef DL_DECL + int flags = RTLD_LAZY | RTLD_GLOBAL; +# ifdef RTLD_DEEPBIND + flags |= RTLD_DEEPBIND; +# endif + void *handle = dlopen("./libdef.so", flags); + if (!handle) { + fprintf(stderr, "dlopen: %s\n", dlerror()); + return 1; + } + + decl_p = (int (*)(void)) dlsym(handle, "decl"); + if (!decl_p) { + fprintf(stderr, "dlsym: %s\n", dlerror()); + return 1; + } +#else + decl_p = decl; +#endif + + int ret = decl_p(); + if (!ret) { + fprintf(stderr, "FAIL\n"); + } else { + fprintf(stderr, "OK\n"); + } + + return !ret; +} diff --git a/ext/opcache/jit/tls/testing/test.sh b/ext/opcache/jit/tls/testing/test.sh new file mode 100755 index 0000000000000..c6b003caafddd --- /dev/null +++ b/ext/opcache/jit/tls/testing/test.sh @@ -0,0 +1,232 @@ +#!/bin/sh + +set -e +cd "$(dirname "$0")" + +print_test() { + echo "Testing: $1 (CC=$CC LD=$LD CFLAGS=$CFLAGS)" +} + +exe_def_static_user() { + print_test "TLS var defined in executable, used in same object" + + rm -f main + + $CC $CFLAGS -ggdb3 -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -o user.o -c user.c + $CC $CFLAGS -ggdb3 -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -ggdb3 -o main main.c def.o user.o tls.o + + ./main +} + +exe_def_shared_user() { + print_test "TLS var defined in executable, used in shared library" + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS $LDFLAGS -shared -o libuser.so user.o tls.o + + $CC $CFLAGS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -ggdb3 -fPIC -o main main.c def.o -Wl,-rpath,$(pwd) -L. -luser + + ./main +} + +shared_def_static_user() { + print_test "TLS var defined in shared library, used in same object" + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o user.o tls.o + + $CC $CFLAGS $LDFLAGS -ggdb3 -fPIC -o main main.c -Wl,-rpath,$(pwd) -L. -ldef + + ./main +} + +shared_def_shared_user() { + print_test "TLS var defined in shared object, used in other shared object" + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS $LDFLAGS -shared -o libuser.so user.o tls.o + + $CC $CFLAGS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o -Wl,-rpath,$(pwd) -L. -luser + + $CC $CFLAGS $LDFLAGS -ggdb3 -fPIC -o main main.c -Wl,-rpath,$(pwd) -L. -ldef + + ./main +} + +shared_def_static_user_no_surplus() { + print_test "TLS var defined in shared library, used in same object. Likely no static TLS surplus." + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS -DNO_SURPLUS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o tls.o user.o + + $CC $CFLAGS -DNO_SURPLUS $LDFLAGS -ggdb3 -fPIC -o main main.c -Wl,-rpath,$(pwd) -L. -ldef + + ./main +} + +shared_def_shared_user_no_surplus() { + print_test "TLS var defined in shared object, used in other shared object. Likely no static TLS surplus." + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS $LDFLAGS -shared -o libuser.so user.o tls.o + + $CC $CFLAGS -DNO_SURPLUS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o -Wl,-rpath,$(pwd) -L. -luser + + $CC $CFLAGS -DNO_SURPLUS $LDFLAGS -ggdb3 -fPIC -o main main.c -Wl,-rpath,$(pwd) -L. -ldef + + ./main +} + +dl_def_static_user() { + print_test "TLS var defined in dl()'ed object, used in same object" + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o user.o tls.o + + $CC $CFLAGS $LDFLAGS -DDL_DECL -ggdb3 -fPIC -o main main.c + + ./main +} + +dl_def_shared_user() { + print_test "TLS var defined in dl()'ed object, used in other shared object" + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS $LDFLAGS -shared -o libuser.so user.o tls.o + + $CC $CFLAGS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o -Wl,-rpath,$(pwd) -L. -luser + + $CC $CFLAGS $LDFLAGS -DDL_DECL -ggdb3 -fPIC -o main main.c + + ./main +} + +dl_def_static_user_no_surplus() { + print_test "TLS var defined in dl()'ed object, used in same object. Likely no surplus TLS" + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS -DNO_SURPLUS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o user.o tls.o + + $CC $CFLAGS -DNO_SURPLUS $LDFLAGS -DDL_DECL -ggdb3 -fPIC -o main main.c + + ./main +} + +dl_def_shared_user_no_surplus() { + print_test "TLS var defined in dl()'ed object, used in other shared object. Likely no surplus TLS" + + rm -f main + + $CC $CFLAGS -ggdb3 -fPIC -o tls.o -c $TLSC + $CC $CFLAGS -ggdb3 -fPIC -o user.o -c user.c + $CC $CFLAGS $LDFLAGS -shared -o libuser.so user.o tls.o + + $CC $CFLAGS -DNO_SURPLUS -ggdb3 -fPIC -o def.o -c def.c + $CC $CFLAGS $LDFLAGS -shared -o libdef.so def.o -Wl,-rpath,$(pwd) -L. -luser + + $CC $CFLAGS -DNO_SURPLUS $LDFLAGS -DDL_DECL -ggdb3 -fPIC -o main main.c + + ./main +} + +if [ -z "$TLSC" ]; then + echo "Variable TLSC is not set" >&2 + exit 1 +fi + +root=$(pwd)/../../../../.. + +# Cheap musl detection +if test -f /etc/alpine-release; then + MUSL="$CFLAGS -D__MUSL__" +else + MUSL= +fi + +if [ "${STATIC_SUPPORT:-yes}" = "yes" ]; then + STATIC=-static +fi + +for CC in clang gcc; do + if [ $CC = gcc ] && [ -f /etc/freebsd-update.conf ]; then + RPATH=-Wl,-rpath,/usr/local/lib/gcc13 + else + RPATH= + fi + case $CC in + gcc) + LDs="" + for l in bdf gold; do + if command -v ld.$l >/dev/null 2>&1; then + LDs="$LDs $l" + fi + done + if [ -z "$LDs" ]; then + LDs=ld + fi + ;; + clang) + LDs="ld" + if command -v ld.lld >/dev/null 2>&1; then + LDs="$LDs lld" + fi + ;; + esac + for LD in $LDs; do + for opt in -O0 -O3; do + CFLAGS="$MACHINE $MUSL $opt -Werror -I$root/ext/opcache -I$root/Zend -I$root" + LDFLAGS="$MACHINE -fuse-ld=$LD $RPATH" + + for pic in "-fPIC" "-fno-PIC $STATIC"; do + CFLAGS="$CFLAGS $pic" exe_def_static_user + done + shared_def_static_user + shared_def_static_user_no_surplus + dl_def_static_user + dl_def_static_user_no_surplus + if [ "$EXTERN_TLS_SUPPORT" = yes ]; then + exe_def_shared_user + shared_def_shared_user + shared_def_shared_user_no_surplus + dl_def_shared_user + dl_def_shared_user_no_surplus + fi + done + done +done + +echo "All OK" >&2 diff --git a/ext/opcache/jit/tls/testing/user.c b/ext/opcache/jit/tls/testing/user.c new file mode 100644 index 0000000000000..c27e608f3f4b1 --- /dev/null +++ b/ext/opcache/jit/tls/testing/user.c @@ -0,0 +1,28 @@ + +/* _tsrm_ls_cache is used / inspected here */ + +#include "../zend_jit_tls.h" + +extern __thread void* _tsrm_ls_cache; + +int test(void) +{ + size_t tcb_offset = 0; + size_t module_index = -1; + size_t module_offset = -1; + + /* Ensure the slot is allocated */ + _tsrm_ls_cache = NULL; + + zend_result result = zend_jit_resolve_tsrm_ls_cache_offsets( + &tcb_offset, &module_index, &module_offset); + + printf("tcb_offset: %zd; module_index: %zd; module_offset: %zd\n", + tcb_offset, module_index, module_offset); + + if (result != SUCCESS) { + return 0; + } + + return zend_jit_tsrm_ls_cache_address(tcb_offset, module_index, module_offset) == &_tsrm_ls_cache; +} diff --git a/ext/opcache/jit/tls/zend_jit_tls.h b/ext/opcache/jit/tls/zend_jit_tls.h new file mode 100644 index 0000000000000..5f90429267256 --- /dev/null +++ b/ext/opcache/jit/tls/zend_jit_tls.h @@ -0,0 +1,40 @@ +/* + * +----------------------------------------------------------------------+ + * | Zend JIT | + * +----------------------------------------------------------------------+ + * | Copyright (c) The PHP Group | + * +----------------------------------------------------------------------+ + * | This source file is subject to version 3.01 of the PHP license, | + * | that is bundled with this package in the file LICENSE, and is | + * | available through the world-wide-web at the following url: | + * | https://www.php.net/license/3_01.txt | + * | If you did not receive a copy of the PHP license and are unable to | + * | obtain it through the world-wide-web, please send a note to | + * | license@php.net so we can mail you a copy immediately. | + * +----------------------------------------------------------------------+ + * | Authors: Arnaud Le Blanc | + * +----------------------------------------------------------------------+ + */ + +#ifndef ZEND_JIT_TLS_H +#define ZEND_JIT_TLS_H + +#include "Zend/zend_types.h" + +#include +#include + +zend_result zend_jit_resolve_tsrm_ls_cache_offsets( + size_t *tcb_offset, + size_t *module_index, + size_t *module_offset +); + +/* Used for testing */ +void *zend_jit_tsrm_ls_cache_address( + size_t tcb_offset, + size_t module_index, + size_t module_offset +); + +#endif /* ZEND_JIT_TLS_H */ diff --git a/ext/opcache/jit/tls/zend_jit_tls_aarch64.c b/ext/opcache/jit/tls/zend_jit_tls_aarch64.c new file mode 100644 index 0000000000000..24f0f88454b63 --- /dev/null +++ b/ext/opcache/jit/tls/zend_jit_tls_aarch64.c @@ -0,0 +1,257 @@ +/* + * +----------------------------------------------------------------------+ + * | Zend JIT | + * +----------------------------------------------------------------------+ + * | Copyright (c) The PHP Group | + * +----------------------------------------------------------------------+ + * | This source file is subject to version 3.01 of the PHP license, | + * | that is bundled with this package in the file LICENSE, and is | + * | available through the world-wide-web at the following url: | + * | https://www.php.net/license/3_01.txt | + * | If you did not receive a copy of the PHP license and are unable to | + * | obtain it through the world-wide-web, please send a note to | + * | license@php.net so we can mail you a copy immediately. | + * +----------------------------------------------------------------------+ + * | Authors: Arnaud Le Blanc | + * +----------------------------------------------------------------------+ + */ + +#include "Zend/zend_portability.h" +#include "Zend/zend_types.h" +#include "TSRM/TSRM.h" +#include "zend_accelerator_debug.h" + +#include +#include + +TSRMLS_CACHE_EXTERN(); + +/* https://developer.arm.com/documentation/ddi0602/2025-03/Base-Instructions/ADRP--Form-PC-relative-address-to-4KB-page- */ +#define AARCH64_ADRP_IMM_MASK 0x60ffffe0 /* bits 30-29, 23-5 */ +#define AARCH64_ADRP_IMMHI_MASK 0x00ffffe0 /* bits 23-5 */ +#define AARCH64_ADRP_IMMLO_MASK 0x60000000 /* bits 30-29 */ +#define AARCH64_ADRP_IMMHI_START 5 +#define AARCH64_ADRP_IMMLO_START 29 +#define AARCH64_ADRP_IMMLO_WIDTH 2 + +#define AARCH64_LDR_UNSIGNED_IMM_MASK 0x003ffc00 /* bits 21-10 */ +#define AARCH64_ADD_IMM_MASK 0x003ffc00 /* bits 21-10 */ +#define AARCH64_MOVZ_IMM_MASK 0x001fffe0 /* bits 20-5 */ +#define AARCH64_MOVZ_HW_MASK 0x00600000 /* bits 22-21 */ +#define AARCH64_MOVK_IMM_MASK 0x001fffe0 /* bits 20-5 */ +#define AARCH64_MOVK_HW_MASK 0x00600000 /* bits 22-21 */ +#define AARCH64_NOP 0xd503201f + +#undef USE_FALLBACK + +#ifdef __MUSL__ + +# define DTV_OFFSET -8 +# define DTV_INDEX_GAP 0 + +typedef struct _dtv_pointer_t { + uintptr_t val; +} dtv_pointer_t; + +typedef struct _tls_descriptor { + size_t index; + size_t offset; +} tls_descriptor; + +#elif defined(__FreeBSD__) + +# define DTV_OFFSET 0 +/* Index is offset by 1 on FreeBSD (https://github.com/freebsd/freebsd-src/blob/22ca6db50f4e6bd75a141f57cf953d8de6531a06/lib/libc/gen/tls.c#L88) */ +# define DTV_INDEX_GAP 1 + +typedef struct _dtv_pointer_t { + uintptr_t val; +} dtv_pointer_t; + +/* https://github.com/freebsd/freebsd-src/blob/c52ca7dd09066648b1cc40f758289404d68ab886/libexec/rtld-elf/aarch64/reloc.c#L180-L184 */ +typedef struct _tls_descriptor { + void* thunk; + int index; + size_t offset; +} tls_descriptor; + +#elif defined(__GLIBC__) + +# define DTV_OFFSET 0 +# define DTV_INDEX_GAP 0 + +typedef struct _dtv_pointer_t { + uintptr_t val; + uintptr_t _; +} dtv_pointer_t; + +typedef struct _tls_descriptor { + size_t index; + size_t offset; +} tls_descriptor; + +#else +# define USE_FALLBACK 1 +#endif + +zend_result zend_jit_resolve_tsrm_ls_cache_offsets( + size_t *tcb_offset, + size_t *module_index, + size_t *module_offset +) { +#ifdef USE_FALLBACK + return FAILURE; +#else + *tcb_offset = tsrm_get_ls_cache_tcb_offset(); + if (*tcb_offset != 0) { + return SUCCESS; + } + + void *addr; + uint32_t *insn; + void *thread_pointer; + + __asm__ __volatile__( + /* Load thread pointer address */ + "mrs %0, tpidr_el0\n" + /* Load next instruction address */ + "adr %1, .+4\n\t" + /* General Dynamic code sequence as expected by linkers */ + "adrp x0, :tlsdesc:_tsrm_ls_cache\n" + "ldr x1, [x0, #:tlsdesc_lo12:_tsrm_ls_cache]\n" + "add x0, x0, :tlsdesc_lo12:_tsrm_ls_cache\n" + ".tlsdesccall _tsrm_ls_cache\n" + "blr x1\n" + "mrs x8, tpidr_el0\n" + "add %2, x8, x0\n" + : "=r" (thread_pointer), "=r" (insn), "=r" (addr) + : + : "x0", "x1", "x8"); + + ZEND_ASSERT(addr == &_tsrm_ls_cache); + + /* Check if the general dynamic code was relaxed by the linker */ + + // adrp x0, #any + if ((insn[0] & ~AARCH64_ADRP_IMM_MASK) != 0x90000000) { + zend_accel_error(ACCEL_LOG_DEBUG, "adrp insn does not match: 0x%08" PRIx32 "\n", insn[0]); + goto code_changed; + } + + // ldr x1, [x0, #any] + if ((insn[1] & ~AARCH64_LDR_UNSIGNED_IMM_MASK) != 0xf9400001) { + zend_accel_error(ACCEL_LOG_DEBUG, "ldr insn does not match: 0x%08" PRIx32 "\n", insn[1]); + goto code_changed; + } + + // add x0, x0, any + if ((insn[2] & ~AARCH64_ADD_IMM_MASK) != 0x91000000) { + zend_accel_error(ACCEL_LOG_DEBUG, "add insn does not match: 0x%08" PRIx32 "x\n", insn[2]); + goto code_changed; + } + + /* Code is intact, we can extract immediate values */ + + uint64_t adrp_immhi = (uint64_t)((insn[0] & AARCH64_ADRP_IMMHI_MASK) >> AARCH64_ADRP_IMMHI_START); + uint64_t adrp_immlo = (uint64_t)((insn[0] & AARCH64_ADRP_IMMLO_MASK) >> AARCH64_ADRP_IMMLO_START); + uint64_t adrp_imm = ((adrp_immhi << AARCH64_ADRP_IMMLO_WIDTH) | adrp_immlo) << 12; + uint64_t add_imm = (uint64_t)(insn[2] & AARCH64_ADD_IMM_MASK) >> 10; + uint64_t pc = (uint64_t)insn; + uintptr_t **where = (uintptr_t**)((pc & ~(4096-1)) + adrp_imm + add_imm); + + /* See https://github.com/ARM-software/abi-aa/blob/2a70c42d62e9c3eb5887fa50b71257f20daca6f9/aaelf64/aaelf64.rst + * section "Relocations for thread-local storage". + * The first entry holds a pointer to the variable's TLS descriptor resolver + * function and the second entry holds a platform-specific offset or + * pointer. */ + tls_descriptor *tlsdesc = (tls_descriptor*)(where[1]); + + if ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer == (uintptr_t)tlsdesc) { + zend_accel_error(ACCEL_LOG_DEBUG, "static tls at offset %p from thread pointer (inferred from tlsdesc)\n", tlsdesc); + *tcb_offset = (uintptr_t)tlsdesc; + return SUCCESS; + } + + *module_index = (tlsdesc->index + DTV_INDEX_GAP) * sizeof(dtv_pointer_t); + *module_offset = tlsdesc->offset; + +# if ZEND_DEBUG + /* We've got the TLS descriptor. Double check: */ + + dtv_pointer_t *dtv = *(dtv_pointer_t**)((uintptr_t)thread_pointer + DTV_OFFSET); + addr = (void*)(((dtv_pointer_t*)((char*)dtv + *module_index))->val + *module_offset); + + ZEND_ASSERT(addr == &_tsrm_ls_cache); +# endif + + zend_accel_error(ACCEL_LOG_DEBUG, "dynamic tls module idx %zu offset %zu (inferred from code)\n", (size_t)tlsdesc->index, tlsdesc->offset); + + return SUCCESS; + +code_changed: + + /* Code was changed by the linker. Check if we recognize the updated code */ + + // movz x0, #0, lsl #16 + if ((insn[0] & ~AARCH64_MOVZ_IMM_MASK) != 0xd2a00000) { + zend_accel_error(ACCEL_LOG_DEBUG, "movz insn does not match: 0x%08" PRIx32 "\n", insn[0]); + return FAILURE; + } + + // movk x0, #0x10 + if ((insn[1] & ~AARCH64_MOVK_IMM_MASK) != 0xf2800000) { + zend_accel_error(ACCEL_LOG_DEBUG, "movk insn does not match: 0x%08" PRIx32 "\n", insn[1]); + return FAILURE; + } + + // nop + for (int i = 0; i < 2; i++) { + if (insn[2+i] != AARCH64_NOP) { + zend_accel_error(ACCEL_LOG_DEBUG, "nop(%d) insn does not match: 0x%08" PRIx32 "\n", i, insn[2+i]); + return FAILURE; + } + } + + /* Extract immediate values */ + + uint64_t movz_imm = (insn[0] & AARCH64_MOVZ_IMM_MASK) >> 5; + uint64_t movz_shift = (((insn[0] & AARCH64_MOVZ_HW_MASK) >> 21) << 4); + uint64_t movk_imm = (insn[1] & AARCH64_MOVK_IMM_MASK) >> 5; + uint64_t offset = (movz_imm << movz_shift) | movk_imm; + + if ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer == offset) { + zend_accel_error(ACCEL_LOG_DEBUG, "static tls at offset %" PRIxPTR " from thread pointer (inferred from code)\n", offset); + *tcb_offset = offset; + return SUCCESS; + } + + zend_accel_error(ACCEL_LOG_DEBUG, "static tls offset does not match: %" PRIxPTR " (expected %" PRIxPTR ")\n", + offset, ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer)); + + return FAILURE; +#endif +} + +/* Used for testing */ +void *zend_jit_tsrm_ls_cache_address( + size_t tcb_offset, + size_t module_index, + size_t module_offset +) { +#ifndef USE_FALLBACK + char *thread_pointer; + __asm__ __volatile__( + "mrs %0, tpidr_el0\n" + : "=r" (thread_pointer) + ); + + if (tcb_offset) { + return thread_pointer + tcb_offset; + } + if (module_index != (size_t)-1 && module_offset != (size_t)-1) { + dtv_pointer_t *dtv = *(dtv_pointer_t**)((uintptr_t)thread_pointer + DTV_OFFSET); + return (void*)(((dtv_pointer_t*)((char*)dtv + module_index))->val + module_offset); + } +#endif + return NULL; +} diff --git a/ext/opcache/jit/tls/zend_jit_tls_darwin.c b/ext/opcache/jit/tls/zend_jit_tls_darwin.c new file mode 100644 index 0000000000000..47a2f01a5a0ae --- /dev/null +++ b/ext/opcache/jit/tls/zend_jit_tls_darwin.c @@ -0,0 +1,82 @@ +/* + * +----------------------------------------------------------------------+ + * | Zend JIT | + * +----------------------------------------------------------------------+ + * | Copyright (c) The PHP Group | + * +----------------------------------------------------------------------+ + * | This source file is subject to version 3.01 of the PHP license, | + * | that is bundled with this package in the file LICENSE, and is | + * | available through the world-wide-web at the following url: | + * | https://www.php.net/license/3_01.txt | + * | If you did not receive a copy of the PHP license and are unable to | + * | obtain it through the world-wide-web, please send a note to | + * | license@php.net so we can mail you a copy immediately. | + * +----------------------------------------------------------------------+ + * | Authors: Dmitry Stogov | + * +----------------------------------------------------------------------+ + */ + +#include "Zend/zend_portability.h" +#include "Zend/zend_types.h" +#include "TSRM/TSRM.h" +#include "zend_accelerator_debug.h" + +#include +#include + +TSRMLS_CACHE_EXTERN(); + +zend_result zend_jit_resolve_tsrm_ls_cache_offsets( + size_t *tcb_offset, + size_t *module_index, + size_t *module_offset +) { + *tcb_offset = tsrm_get_ls_cache_tcb_offset(); + if (*tcb_offset != 0) { + return SUCCESS; + } + +#if defined(__x86_64__) + size_t *ti; + __asm__ __volatile__( + "leaq __tsrm_ls_cache(%%rip),%0" + : "=r" (ti)); + *module_offset = ti[2]; + *module_index = ti[1] * 8; + + return SUCCESS; +#endif + + return FAILURE; +} + +/* Used for testing */ +void *zend_jit_tsrm_ls_cache_address( + size_t tcb_offset, + size_t module_index, + size_t module_offset +) { + +#if defined(__x86_64__) + if (tcb_offset) { + char *addr; + __asm__ __volatile__( + "movq %%gs:(%1), %0\n" + : "=r" (addr) + : "r" (tcb_offset) + ); + return addr; + } + if (module_index != (size_t)-1 && module_offset != (size_t)-1) { + char *base; + __asm__ __volatile__( + "movq %%gs:(%1), %0\n" + : "=r" (base) + : "r" (module_index) + ); + return base + module_offset; + } +#endif + + return NULL; +} diff --git a/ext/opcache/jit/tls/zend_jit_tls_win.c b/ext/opcache/jit/tls/zend_jit_tls_win.c new file mode 100644 index 0000000000000..23f0c1e79baaf --- /dev/null +++ b/ext/opcache/jit/tls/zend_jit_tls_win.c @@ -0,0 +1,64 @@ +/* + * +----------------------------------------------------------------------+ + * | Zend JIT | + * +----------------------------------------------------------------------+ + * | Copyright (c) The PHP Group | + * +----------------------------------------------------------------------+ + * | This source file is subject to version 3.01 of the PHP license, | + * | that is bundled with this package in the file LICENSE, and is | + * | available through the world-wide-web at the following url: | + * | https://www.php.net/license/3_01.txt | + * | If you did not receive a copy of the PHP license and are unable to | + * | obtain it through the world-wide-web, please send a note to | + * | license@php.net so we can mail you a copy immediately. | + * +----------------------------------------------------------------------+ + * | Authors: Dmitry Stogov | + * +----------------------------------------------------------------------+ + */ + +#include "Zend/zend_portability.h" +#include "Zend/zend_types.h" +#include "TSRM/TSRM.h" +#include "zend_accelerator_debug.h" + +#include +#include + +TSRMLS_CACHE_EXTERN(); + +extern uint32_t _tls_index; +extern char *_tls_start; +extern char *_tls_end; + +zend_result zend_jit_resolve_tsrm_ls_cache_offsets( + size_t *tcb_offset, + size_t *module_index, + size_t *module_offset +) { + /* To find offset of "_tsrm_ls_cache" in TLS segment we perform a linear scan of local TLS memory */ + /* Probably, it might be better solution */ +#ifdef _WIN64 + void ***tls_mem = ((void****)__readgsqword(0x58))[_tls_index]; +#else + void ***tls_mem = ((void****)__readfsdword(0x2c))[_tls_index]; +#endif + void *val = _tsrm_ls_cache; + size_t offset = 0; + size_t size = (char*)&_tls_end - (char*)&_tls_start; + + while (offset < size) { + if (*tls_mem == val) { + *module_index = _tls_index * sizeof(void*); + *module_offset = offset; + return SUCCESS; + } + tls_mem++; + offset += sizeof(void*); + } + + if (offset >= size) { + zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: offset >= size"); + } + + return FAILURE; +} diff --git a/ext/opcache/jit/tls/zend_jit_tls_x86.c b/ext/opcache/jit/tls/zend_jit_tls_x86.c new file mode 100644 index 0000000000000..4e06bbd1eacde --- /dev/null +++ b/ext/opcache/jit/tls/zend_jit_tls_x86.c @@ -0,0 +1,241 @@ +/* + * +----------------------------------------------------------------------+ + * | Zend JIT | + * +----------------------------------------------------------------------+ + * | Copyright (c) The PHP Group | + * +----------------------------------------------------------------------+ + * | This source file is subject to version 3.01 of the PHP license, | + * | that is bundled with this package in the file LICENSE, and is | + * | available through the world-wide-web at the following url: | + * | https://www.php.net/license/3_01.txt | + * | If you did not receive a copy of the PHP license and are unable to | + * | obtain it through the world-wide-web, please send a note to | + * | license@php.net so we can mail you a copy immediately. | + * +----------------------------------------------------------------------+ + * | Authors: Arnaud Le Blanc | + * +----------------------------------------------------------------------+ + */ + +#include "zend_portability.h" +#include "zend_types.h" +#include "TSRM/TSRM.h" +#include "zend_accelerator_debug.h" +#include "zend_jit_tls.h" + +#include +#include + +TSRMLS_CACHE_EXTERN(); + +#undef USE_FALLBACK + +#ifdef __MUSL__ + +# define DTV_OFFSET 4 +# define DTV_INDEX_GAP 0 + +typedef struct _dtv_pointer_t { + uintptr_t val; +} dtv_pointer_t; + +typedef struct _tls_descriptor { + size_t index; + size_t offset; +} tls_descriptor; + +#elif defined(__FreeBSD__) + +# define DTV_OFFSET 4 +# define DTV_INDEX_GAP 1 + +typedef struct _dtv_pointer_t { + uintptr_t val; +} dtv_pointer_t; + +/* https://github.com/freebsd/freebsd-src/blob/6b94546a7ea2dc593f5765bd5465a8b7bb80c325/libexec/rtld-elf/i386/rtld_machdep.h#L65 */ +typedef struct _tls_descriptor { + unsigned long index; + unsigned long offset; +} tls_descriptor; + +#elif defined(__GLIBC__) + +# define DTV_OFFSET 4 +# define DTV_INDEX_GAP 0 + +typedef struct _dtv_pointer_t { + uintptr_t val; + uintptr_t _; +} dtv_pointer_t; + +typedef struct _tls_descriptor { + size_t index; + size_t offset; +} tls_descriptor; + +#else +# define USE_FALLBACK 1 +#endif + +zend_result zend_jit_resolve_tsrm_ls_cache_offsets( + size_t *tcb_offset, + size_t *module_index, + size_t *module_offset +) { +#ifdef USE_FALLBACK + return FAILURE; +#else + *tcb_offset = tsrm_get_ls_cache_tcb_offset(); + if (*tcb_offset != 0) { + return SUCCESS; + } + + void *t_addr; + unsigned char *code; + void *thread_pointer; + + __asm__ __volatile__( + /* Load next instruction address */ + "call 1f\n" + ".subsection 1\n" + "1:\n" + "movl (%%esp), %%ebx\n" + "movl %%ebx, %%esi\n" + "ret\n" + ".previous\n" + /* General Dynamic code sequence as expected by linkers */ + "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n" + "leal _tsrm_ls_cache@TLSGD(,%%ebx,1), %%eax\n" + "call ___tls_get_addr@PLT\n" + /* Load thread pointer address */ + "movl %%gs:0, %%ebx\n" + : "=a" (t_addr), "=S" (code), "=b" (thread_pointer) + ); + + ZEND_ASSERT(t_addr == &_tsrm_ls_cache); + + /* Check if the general dynamic code was relaxed by the linker */ + + // addl any,%ebx + if (memcmp(&code[0], "\x81\xc3", 2) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[0], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "addl insn does not match: 0x%16" PRIx64 "\n", bytes); + goto code_changed; + } + + // leal any(,%ebx,1),%eax + if (memcmp(&code[6], "\x8d\x04\x1d", 3) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[6], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "leal insn does not match: 0x%16" PRIx64 "\n", bytes); + goto code_changed; + } + + // call any + if (memcmp(&code[13], "\xe8", 1) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[13], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "call insn does not match: 0x%16" PRIx64 "\n", bytes); + goto code_changed; + } + + /* Code is intact, we can extract immediate values */ + + uint32_t addl_imm = ((uint32_t)code[5] << 24) + | ((uint32_t)code[4] << 16) + | ((uint32_t)code[3] << 8) + | ((uint32_t)code[2]); + uint32_t leal_imm = ((uint32_t)code[12] << 24) + | ((uint32_t)code[11] << 16) + | ((uint32_t)code[10] << 8) + | ((uint32_t)code[9]); + + tls_descriptor *tlsdesc = (tls_descriptor*)(leal_imm + addl_imm + (uintptr_t)code); + + *module_index = (tlsdesc->index + DTV_INDEX_GAP) * sizeof(dtv_pointer_t); + *module_offset = tlsdesc->offset; + +# if ZEND_DEBUG + /* We've got the TLS descriptor. Double check: */ + + dtv_pointer_t *dtv = *(dtv_pointer_t**)((uintptr_t)thread_pointer + DTV_OFFSET); + void *addr = (void*)(((dtv_pointer_t*)((char*)dtv + *module_index))->val + *module_offset); + + ZEND_ASSERT(addr == &_tsrm_ls_cache); +# endif + + zend_accel_error(ACCEL_LOG_DEBUG, "dynamic tls module idx %zu offset %zu (inferred from code)\n", + (size_t)tlsdesc->index, (size_t)tlsdesc->offset); + + return SUCCESS; + +code_changed: + + /* Code was changed by the linker. Check if we recognize the updated code */ + + /* + * 81 c3 98 2d 00 00 addl $0x2d98,%ebx + * 65 a1 00 00 00 00 movl %gs:0x0,%eax + * 81 e8 04 00 00 00 subl $0x4,%eax + */ + + // movl %gs:0x0,%eax + if (memcmp(&code[6], "\x65\xa1\x00\x00\x00\x00", 6) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[6], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "movl insn does not match: 0x%16" PRIx64 "\n", bytes); + return FAILURE; + } + + // subl $any,%eax + if (memcmp(&code[12], "\x81\xe8", 2) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[6], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "subl insn does not match: 0x%16" PRIx64 "\n", bytes); + return FAILURE; + } + + /* Extract immediate values */ + + uint32_t offset = -(((uint32_t)code[17] << 24) + | ((uint32_t)code[16] << 16) + | ((uint32_t)code[15] << 8) + | ((uint32_t)code[14])); + + if ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer == offset) { + zend_accel_error(ACCEL_LOG_DEBUG, "static tls at offset %" PRIx32 " from thread pointer (inferred from code)\n", offset); + *tcb_offset = offset; + return SUCCESS; + } + + zend_accel_error(ACCEL_LOG_DEBUG, "static tls offset does not match: 0x%" PRIx32 " (expected 0x%" PRIx32 ")\n", + offset, (uint32_t)((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer)); + + return FAILURE; +#endif +} + +/* Used for testing */ +void *zend_jit_tsrm_ls_cache_address( + size_t tcb_offset, + size_t module_index, + size_t module_offset +) { +#ifndef USE_FALLBACK + char *thread_pointer; + __asm__ __volatile__( + "movl %%gs:0, %0\n" + : "=r" (thread_pointer) + ); + + if (tcb_offset) { + return thread_pointer + tcb_offset; + } + if (module_index != (size_t)-1 && module_offset != (size_t)-1) { + dtv_pointer_t *dtv = *(dtv_pointer_t**)((uintptr_t)thread_pointer + DTV_OFFSET); + return (void*)(((dtv_pointer_t*)((char*)dtv + module_index))->val + module_offset); + } +#endif + return NULL; +} diff --git a/ext/opcache/jit/tls/zend_jit_tls_x86_64.c b/ext/opcache/jit/tls/zend_jit_tls_x86_64.c new file mode 100644 index 0000000000000..11ffe495fcbb3 --- /dev/null +++ b/ext/opcache/jit/tls/zend_jit_tls_x86_64.c @@ -0,0 +1,224 @@ +/* + * +----------------------------------------------------------------------+ + * | Zend JIT | + * +----------------------------------------------------------------------+ + * | Copyright (c) The PHP Group | + * +----------------------------------------------------------------------+ + * | This source file is subject to version 3.01 of the PHP license, | + * | that is bundled with this package in the file LICENSE, and is | + * | available through the world-wide-web at the following url: | + * | https://www.php.net/license/3_01.txt | + * | If you did not receive a copy of the PHP license and are unable to | + * | obtain it through the world-wide-web, please send a note to | + * | license@php.net so we can mail you a copy immediately. | + * +----------------------------------------------------------------------+ + * | Authors: Arnaud Le Blanc | + * +----------------------------------------------------------------------+ + */ + +#include "zend_portability.h" +#include "zend_types.h" +#include "TSRM/TSRM.h" +#include "zend_accelerator_debug.h" +#include "zend_jit_tls.h" + +#include +#include + +TSRMLS_CACHE_EXTERN(); + +#undef USE_FALLBACK + +#ifdef __MUSL__ + +# define DTV_OFFSET 8 +# define DTV_INDEX_GAP 0 + +typedef struct _dtv_pointer_t { + uintptr_t val; +} dtv_pointer_t; + +typedef struct _tls_descriptor { + size_t index; + size_t offset; +} tls_descriptor; + +#elif defined(__FreeBSD__) + +# define DTV_OFFSET 8 +# define DTV_INDEX_GAP 1 + +typedef struct _dtv_pointer_t { + uintptr_t val; +} dtv_pointer_t; + +/* https://github.com/freebsd/freebsd-src/blob/6b94546a7ea2dc593f5765bd5465a8b7bb80c325/libexec/rtld-elf/amd64/rtld_machdep.h#L65 */ +typedef struct _tls_descriptor { + unsigned long index; + unsigned long offset; +} tls_descriptor; + +#elif defined(__GLIBC__) + +# define DTV_OFFSET 8 +# define DTV_INDEX_GAP 0 + +typedef struct _dtv_pointer_t { + uintptr_t val; + uintptr_t _; +} dtv_pointer_t; + +typedef struct _tls_descriptor { + size_t index; + size_t offset; +} tls_descriptor; + +#else +# define USE_FALLBACK 1 +#endif + +zend_result zend_jit_resolve_tsrm_ls_cache_offsets( + size_t *tcb_offset, + size_t *module_index, + size_t *module_offset +) { +#ifdef USE_FALLBACK + return FAILURE; +#else + *tcb_offset = tsrm_get_ls_cache_tcb_offset(); + if (*tcb_offset != 0) { + return SUCCESS; + } + + void *addr; + unsigned char *code; + void *thread_pointer; + + __asm__ __volatile__( + /* Load next instruction address */ + "leaq (%%rip), %%rbx\n" + /* General Dynamic code sequence as expected by linkers */ + ".byte 0x66\n" + "leaq _tsrm_ls_cache@tlsgd(%%rip), %%rdi\n" + ".word 0x6666\n" + "rex64\n" + "call __tls_get_addr\n" + /* Load thread pointer address */ + "movq %%fs:0, %%rsi\n" + : "=a" (addr), "=b" (code), "=S" (thread_pointer) + ); + + ZEND_ASSERT(addr == &_tsrm_ls_cache); + + /* Check if the general dynamic code was relaxed by the linker */ + + // data16 leaq any(%rip),%rdi + if (memcmp(&code[0], "\x66\x48\x8d\x3d", 4) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[0], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "leaq insn does not match: 0x%016" PRIx64 "\n", bytes); + goto code_changed; + } + + // data16 data16 rex.W call any + if (memcmp(&code[8], "\x66\x66\x48\xe8", 4) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[8], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "call insn does not match: 0x%016" PRIx64 "\n", bytes); + goto code_changed; + } + + /* Code is intact, we can extract immediate values */ + + uintptr_t leaq_imm = (uintptr_t)(int32_t)((uint32_t)code[7] << 24) + | ((uint32_t)code[6] << 16) + | ((uint32_t)code[5] << 8) + | ((uint32_t)code[4]); + + tls_descriptor *tlsdesc = (tls_descriptor*)(leaq_imm + (uintptr_t)code + 8 /* leaq */); + + *module_index = ((size_t)tlsdesc->index + DTV_INDEX_GAP) * sizeof(dtv_pointer_t); + *module_offset = (size_t)tlsdesc->offset; + +# if ZEND_DEBUG + /* We've got the TLS descriptor. Double check: */ + + dtv_pointer_t *dtv = *(dtv_pointer_t**)((uintptr_t)thread_pointer + DTV_OFFSET); + addr = (void*)(((dtv_pointer_t*)((char*)dtv + *module_index))->val + *module_offset); + + ZEND_ASSERT(addr == &_tsrm_ls_cache); +# endif + + zend_accel_error(ACCEL_LOG_DEBUG, "dynamic tls module idx %zu offset %zu (inferred from code)\n", + (size_t)tlsdesc->index, (size_t)tlsdesc->offset); + + return SUCCESS; + +code_changed: + + /* Code was changed by the linker. Check if we recognize the updated code */ + + /* + * 64 48 8b 04 25 00 00 00 00 movq %fs:0x0,%rax + * 48 8d 80 f8 ff ff ff leaq -0x8(%rax),%rax + */ + + // movq %fs:0x0,%rax + if (memcmp(&code[0], "\x64\x48\x8b\x04\x25\x00\x00\x00\x00", 9) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[0], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "movq insn does not match: 0x%016" PRIx64 "\n", bytes); + return FAILURE; + } + + // leaq any(%rax),$rax + if (memcmp(&code[9], "\x48\x8d\x80", 3) != 0) { + uint64_t bytes; + memcpy(&bytes, &code[10], 8); + zend_accel_error(ACCEL_LOG_DEBUG, "leaq insn does not match: 0x%016" PRIx64 "\n", bytes); + return FAILURE; + } + + /* Extract immediate values */ + + uintptr_t offset = (uintptr_t)(int32_t)(((uint32_t)code[15] << 24) + | ((uint32_t)code[14] << 16) + | ((uint32_t)code[13] << 8) + | ((uint32_t)code[12])); + + if ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer == offset) { + *tcb_offset = offset; + zend_accel_error(ACCEL_LOG_DEBUG, "static tls at offset %" PRIxPTR " from thread pointer (inferred from code)\n", offset); + return SUCCESS; + } + + zend_accel_error(ACCEL_LOG_DEBUG, "static tls offset does not match: %" PRIxPTR " (expected %" PRIxPTR ")\n", + offset, ((uintptr_t)&_tsrm_ls_cache - (uintptr_t)thread_pointer)); + + return FAILURE; +#endif +} + +/* Used for testing */ +void *zend_jit_tsrm_ls_cache_address( + size_t tcb_offset, + size_t module_index, + size_t module_offset +) { +#ifndef USE_FALLBACK + char *thread_pointer; + __asm__ __volatile__( + "movq %%fs:0, %0\n" + : "=r" (thread_pointer) + ); + + if (tcb_offset) { + return thread_pointer + tcb_offset; + } + if (module_index != (size_t)-1 && module_offset != (size_t)-1) { + dtv_pointer_t *dtv = *(dtv_pointer_t**)((uintptr_t)thread_pointer + DTV_OFFSET); + return (void*)(((dtv_pointer_t*)((char*)dtv + module_index))->val + module_offset); + } +#endif + return NULL; +} diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index bdf8ce2b007f4..30f49fb73f676 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -48,6 +48,7 @@ #ifdef ZTS int jit_globals_id; +size_t jit_globals_offset; #else zend_jit_globals jit_globals; #endif @@ -77,7 +78,6 @@ int zend_jit_profile_counter_rid = -1; int16_t zend_jit_hot_counters[ZEND_HOT_COUNTERS_COUNT]; const zend_op *zend_jit_halt_op = NULL; -static int zend_jit_vm_kind = 0; #ifdef HAVE_PTHREAD_JIT_WRITE_PROTECT_NP static int zend_write_protect = 1; #endif @@ -90,15 +90,19 @@ static size_t dasm_size = 0; static zend_long jit_bisect_pos = 0; -static const void *zend_jit_runtime_jit_handler = NULL; -static const void *zend_jit_profile_jit_handler = NULL; -static const void *zend_jit_func_hot_counter_handler = NULL; -static const void *zend_jit_loop_hot_counter_handler = NULL; -static const void *zend_jit_func_trace_counter_handler = NULL; -static const void *zend_jit_ret_trace_counter_handler = NULL; -static const void *zend_jit_loop_trace_counter_handler = NULL; +static zend_vm_opcode_handler_t zend_jit_runtime_jit_handler = NULL; +static zend_vm_opcode_handler_t zend_jit_profile_jit_handler = NULL; +static zend_vm_opcode_handler_t zend_jit_func_hot_counter_handler = NULL; +static zend_vm_opcode_handler_t zend_jit_loop_hot_counter_handler = NULL; +static zend_vm_opcode_handler_t zend_jit_func_trace_counter_handler = NULL; +static zend_vm_opcode_handler_t zend_jit_ret_trace_counter_handler = NULL; +static zend_vm_opcode_handler_t zend_jit_loop_trace_counter_handler = NULL; -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS); +#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS); +#else +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS); +#endif static int zend_jit_trace_op_len(const zend_op *opline); static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op *opline); @@ -1417,7 +1421,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op zend_jit_ctx ctx; zend_jit_ctx *jit = &ctx; zend_jit_reg_var *ra = NULL; - void *handler; + zend_vm_opcode_handler_t handler; int call_level = 0; void *checkpoint = NULL; bool recv_emitted = 0; /* emitted at least one RECV opcode */ @@ -3074,7 +3078,11 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons } /* Run-time JIT handler */ -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) +#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) +#else +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) +#endif { #if GCC_GLOBAL_REGS zend_execute_data *execute_data; @@ -3126,7 +3134,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLE #if GCC_GLOBAL_REGS return; // ZEND_VM_CONTINUE #else - return orig_opline; // ZEND_VM_CONTINUE + opline = orig_opline; + ZEND_OPCODE_RETURN(); #endif } @@ -3213,7 +3222,7 @@ static void zend_jit_setup_hot_counters_ex(zend_op_array *op_array, zend_cfg *cf } } - opline->handler = (const void*)zend_jit_func_hot_counter_handler; + opline->handler = zend_jit_func_hot_counter_handler; } if (JIT_G(hot_loop)) { @@ -3223,7 +3232,7 @@ static void zend_jit_setup_hot_counters_ex(zend_op_array *op_array, zend_cfg *cf if ((cfg->blocks[i].flags & ZEND_BB_REACHABLE) && (cfg->blocks[i].flags & ZEND_BB_LOOP_HEADER)) { op_array->opcodes[cfg->blocks[i].start].handler = - (const void*)zend_jit_loop_hot_counter_handler; + zend_jit_loop_hot_counter_handler; } } } @@ -3314,9 +3323,9 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script) memset(&jit_extension->func_info, 0, sizeof(zend_func_info)); jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_FIRST_EXEC; jit_extension->op_array = op_array; - jit_extension->orig_handler = (void*)opline->handler; + jit_extension->orig_handler = opline->handler; ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension); - opline->handler = (const void*)zend_jit_runtime_jit_handler; + opline->handler = zend_jit_runtime_jit_handler; zend_shared_alloc_register_xlat_entry(op_array->opcodes, jit_extension); return SUCCESS; @@ -3344,9 +3353,9 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script) memset(&jit_extension->func_info, 0, sizeof(zend_func_info)); jit_extension->func_info.flags = ZEND_FUNC_JIT_ON_PROF_REQUEST; jit_extension->op_array = op_array; - jit_extension->orig_handler = (void*)opline->handler; + jit_extension->orig_handler = opline->handler; ZEND_SET_FUNC_INFO(op_array, (void*)jit_extension); - opline->handler = (const void*)zend_jit_profile_jit_handler; + opline->handler = zend_jit_profile_jit_handler; zend_shared_alloc_register_xlat_entry(op_array->opcodes, jit_extension); } @@ -3363,6 +3372,17 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script) return FAILURE; } +static void zend_jit_link_func_info(zend_op_array *op_array) +{ + if (!ZEND_FUNC_INFO(op_array)) { + void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes); + + if (jit_extension) { + ZEND_SET_FUNC_INFO(op_array, jit_extension); + } + } +} + int zend_jit_script(zend_script *script) { void *checkpoint; @@ -3450,6 +3470,7 @@ int zend_jit_script(zend_script *script) zend_class_entry *ce; zend_op_array *op_array; zval *zv; + zend_property_info *prop; ZEND_HASH_MAP_FOREACH_VAL(&script->class_table, zv) { if (Z_TYPE_P(zv) == IS_ALIAS_PTR) { @@ -3460,14 +3481,21 @@ int zend_jit_script(zend_script *script) ZEND_ASSERT(ce->type == ZEND_USER_CLASS); ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { - if (!ZEND_FUNC_INFO(op_array)) { - void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes); + zend_jit_link_func_info(op_array); + } ZEND_HASH_FOREACH_END(); - if (jit_extension) { - ZEND_SET_FUNC_INFO(op_array, jit_extension); + if (ce->num_hooked_props > 0) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { + if (prop->hooks) { + for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { + if (prop->hooks[i]) { + op_array = &prop->hooks[i]->op_array; + zend_jit_link_func_info(op_array); + } + } } - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } } ZEND_HASH_FOREACH_END(); } @@ -3547,23 +3575,23 @@ void zend_jit_protect(void) static void zend_jit_init_handlers(void) { - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { - zend_jit_runtime_jit_handler = zend_jit_stub_handlers[jit_stub_hybrid_runtime_jit]; - zend_jit_profile_jit_handler = zend_jit_stub_handlers[jit_stub_hybrid_profile_jit]; - zend_jit_func_hot_counter_handler = zend_jit_stub_handlers[jit_stub_hybrid_func_hot_counter]; - zend_jit_loop_hot_counter_handler = zend_jit_stub_handlers[jit_stub_hybrid_loop_hot_counter]; - zend_jit_func_trace_counter_handler = zend_jit_stub_handlers[jit_stub_hybrid_func_trace_counter]; - zend_jit_ret_trace_counter_handler = zend_jit_stub_handlers[jit_stub_hybrid_ret_trace_counter]; - zend_jit_loop_trace_counter_handler = zend_jit_stub_handlers[jit_stub_hybrid_loop_trace_counter]; - } else { - zend_jit_runtime_jit_handler = (const void*)zend_runtime_jit; - zend_jit_profile_jit_handler = (const void*)zend_jit_profile_helper; - zend_jit_func_hot_counter_handler = (const void*)zend_jit_func_counter_helper; - zend_jit_loop_hot_counter_handler = (const void*)zend_jit_loop_counter_helper; - zend_jit_func_trace_counter_handler = (const void*)zend_jit_func_trace_helper; - zend_jit_ret_trace_counter_handler = (const void*)zend_jit_ret_trace_helper; - zend_jit_loop_trace_counter_handler = (const void*)zend_jit_loop_trace_helper; - } +#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID + zend_jit_runtime_jit_handler = (zend_vm_opcode_handler_t)zend_jit_stub_handlers[jit_stub_hybrid_runtime_jit]; + zend_jit_profile_jit_handler = (zend_vm_opcode_handler_t)zend_jit_stub_handlers[jit_stub_hybrid_profile_jit]; + zend_jit_func_hot_counter_handler = (zend_vm_opcode_handler_t)zend_jit_stub_handlers[jit_stub_hybrid_func_hot_counter]; + zend_jit_loop_hot_counter_handler = (zend_vm_opcode_handler_t)zend_jit_stub_handlers[jit_stub_hybrid_loop_hot_counter]; + zend_jit_func_trace_counter_handler = (zend_vm_opcode_handler_t)zend_jit_stub_handlers[jit_stub_hybrid_func_trace_counter]; + zend_jit_ret_trace_counter_handler = (zend_vm_opcode_handler_t)zend_jit_stub_handlers[jit_stub_hybrid_ret_trace_counter]; + zend_jit_loop_trace_counter_handler = (zend_vm_opcode_handler_t)zend_jit_stub_handlers[jit_stub_hybrid_loop_trace_counter]; +#else + zend_jit_runtime_jit_handler = zend_runtime_jit; + zend_jit_profile_jit_handler = zend_jit_profile_helper; + zend_jit_func_hot_counter_handler = zend_jit_func_counter_helper; + zend_jit_loop_hot_counter_handler = zend_jit_loop_counter_helper; + zend_jit_func_trace_counter_handler = zend_jit_func_trace_helper; + zend_jit_ret_trace_counter_handler = zend_jit_ret_trace_helper; + zend_jit_loop_trace_counter_handler = zend_jit_loop_trace_helper; +#endif } static void zend_jit_globals_ctor(zend_jit_globals *jit_globals) @@ -3682,25 +3710,20 @@ int zend_jit_debug_config(zend_long old_val, zend_long new_val, int stage) void zend_jit_init(void) { #ifdef ZTS - jit_globals_id = ts_allocate_id(&jit_globals_id, sizeof(zend_jit_globals), (ts_allocate_ctor) zend_jit_globals_ctor, (ts_allocate_dtor) zend_jit_globals_dtor); + jit_globals_id = ts_allocate_fast_id(&jit_globals_id, &jit_globals_offset, sizeof(zend_jit_globals), (ts_allocate_ctor) zend_jit_globals_ctor, (ts_allocate_dtor) zend_jit_globals_dtor); #else zend_jit_globals_ctor(&jit_globals); #endif } +#if ZEND_VM_KIND != ZEND_VM_KIND_CALL && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL && ZEND_VM_KIND != ZEND_VM_KIND_HYBRID +# error JIT is compatible only with CALL and HYBRID VM +#endif + int zend_jit_check_support(void) { int i; - zend_jit_vm_kind = zend_vm_kind(); - if (zend_jit_vm_kind != ZEND_VM_KIND_CALL && - zend_jit_vm_kind != ZEND_VM_KIND_HYBRID) { - zend_error(E_WARNING, "JIT is compatible only with CALL and HYBRID VM. JIT disabled."); - JIT_G(enabled) = 0; - JIT_G(on) = 0; - return FAILURE; - } - if (zend_execute_ex != execute_ex) { if (zend_dtrace_enabled) { zend_error(E_WARNING, "JIT is incompatible with DTrace. JIT disabled."); @@ -3845,6 +3868,14 @@ void zend_jit_shutdown(void) #else zend_jit_trace_free_caches(&jit_globals); #endif + + /* Reset global pointers to prevent use-after-free in `zend_jit_status()` + * after gracefully restarting Apache with mod_php, see: + * https://github.com/php/php-src/pull/19212 */ + dasm_ptr = NULL; + dasm_buf = NULL; + dasm_end = NULL; + dasm_size = 0; } static void zend_jit_reset_counters(void) @@ -3901,8 +3932,10 @@ void zend_jit_deactivate(void) zend_jit_profile_counter = 0; } -static void zend_jit_restart_preloaded_op_array(zend_op_array *op_array) +static void zend_jit_restart_preloaded_op_array(zend_op_array *op_array, void *context) { + ZEND_IGNORE_VALUE(context); + zend_func_info *func_info = ZEND_FUNC_INFO(op_array); if (!func_info) { @@ -3926,37 +3959,17 @@ static void zend_jit_restart_preloaded_op_array(zend_op_array *op_array) } } if (func_info->flags & ZEND_FUNC_JIT_ON_FIRST_EXEC) { - opline->handler = (const void*)zend_jit_runtime_jit_handler; + opline->handler = zend_jit_runtime_jit_handler; } else { - opline->handler = (const void*)zend_jit_profile_jit_handler; + opline->handler = zend_jit_profile_jit_handler; } #endif } - if (op_array->num_dynamic_func_defs) { - for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) { - zend_jit_restart_preloaded_op_array(op_array->dynamic_func_defs[i]); - } - } } static void zend_jit_restart_preloaded_script(zend_persistent_script *script) { - zend_class_entry *ce; - zend_op_array *op_array; - - zend_jit_restart_preloaded_op_array(&script->script.main_op_array); - - ZEND_HASH_MAP_FOREACH_PTR(&script->script.function_table, op_array) { - zend_jit_restart_preloaded_op_array(op_array); - } ZEND_HASH_FOREACH_END(); - - ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) { - ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { - if (op_array->type == ZEND_USER_FUNCTION) { - zend_jit_restart_preloaded_op_array(op_array); - } - } ZEND_HASH_FOREACH_END(); - } ZEND_HASH_FOREACH_END(); + zend_foreach_op_array(&script->script, zend_jit_restart_preloaded_op_array, NULL); } void zend_jit_restart(void) diff --git a/ext/opcache/jit/zend_jit.h b/ext/opcache/jit/zend_jit.h index 9178d340a0ede..5e6b225676aa2 100644 --- a/ext/opcache/jit/zend_jit.h +++ b/ext/opcache/jit/zend_jit.h @@ -145,8 +145,9 @@ typedef struct _zend_jit_globals { } zend_jit_globals; #ifdef ZTS -# define JIT_G(v) ZEND_TSRMG(jit_globals_id, zend_jit_globals *, v) +# define JIT_G(v) ZEND_TSRMG_FAST(jit_globals_offset, zend_jit_globals *, v) extern int jit_globals_id; +extern size_t jit_globals_offset; #else # define JIT_G(v) (jit_globals.v) extern zend_jit_globals jit_globals; diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index b20afffa47df0..ce48d10223412 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -16,6 +16,7 @@ +----------------------------------------------------------------------+ */ +#include "Zend/zend_types.h" #include "Zend/zend_API.h" static ZEND_COLD void undef_result_after_exception(void) { @@ -500,8 +501,17 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_r_helper(zend_array *ht, zval *dim, } ZEND_FALLTHROUGH; case IS_NULL: - offset_key = ZSTR_EMPTY_ALLOC(); - goto str_index; + retval = zend_hash_find(ht, ZSTR_EMPTY_ALLOC()); + if (!retval) { + ZVAL_NULL(result); + } else { + ZVAL_COPY_DEREF(result, retval); + } + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (!retval) { + zend_error(E_WARNING, "Undefined array key \"\""); + } + return; case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(dim)); if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { @@ -642,8 +652,16 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_is_helper(zend_array *ht, zval *dim } ZEND_FALLTHROUGH; case IS_NULL: - offset_key = ZSTR_EMPTY_ALLOC(); - goto str_index; + retval = zend_hash_find(ht, ZSTR_EMPTY_ALLOC()); + if (!retval) { + ZVAL_NULL(result); + } else { + ZVAL_COPY_DEREF(result, retval); + } + + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + + return; case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(dim)); if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { @@ -769,9 +787,17 @@ static int ZEND_FASTCALL zend_jit_fetch_dim_isset_helper(zend_array *ht, zval *d return 0; } ZEND_FALLTHROUGH; - case IS_NULL: - offset_key = ZSTR_EMPTY_ALLOC(); - goto str_index; + case IS_NULL: { + int result = 0; + retval = zend_hash_find(ht, ZSTR_EMPTY_ALLOC()); + if (retval) { + result = Z_TYPE_P(retval) > IS_NULL; + } + + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + + return result; + } case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(dim)); if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { @@ -878,6 +904,32 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di } ZEND_FALLTHROUGH; case IS_NULL: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + + execute_data = EG(current_execute_data); + opline = EX(opline); + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { + if (!GC_REFCOUNT(ht)) { + zend_array_destroy(ht); + } + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return NULL; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return NULL; + } offset_key = ZSTR_EMPTY_ALLOC(); goto str_index; case IS_DOUBLE: @@ -1011,6 +1063,36 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_w_helper(zend_array *ht, zval *dim } ZEND_FALLTHROUGH; case IS_NULL: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + GC_TRY_ADDREF(ht); + + execute_data = EG(current_execute_data); + opline = EX(opline); + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) { + if (!GC_REFCOUNT(ht)) { + zend_array_destroy(ht); + } + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + if (opline->opcode == ZEND_ASSIGN_DIM + && ((opline+1)->op1_type & (IS_VAR | IS_TMP_VAR))) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + } + return NULL; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return NULL; + } offset_key = ZSTR_EMPTY_ALLOC(); goto str_index; case IS_DOUBLE: @@ -2561,6 +2643,14 @@ static void ZEND_FASTCALL zend_jit_only_vars_by_reference(zval *arg) zend_error(E_NOTICE, "Only variables should be passed by reference"); } +static void ZEND_FASTCALL zend_jit_invalid_array_use(const zval *container) +{ + /* Warning should not occur on null */ + if (Z_TYPE_P(container) != IS_NULL) { + zend_error(E_WARNING, "Cannot use %s as array", zend_zval_type_name(container)); + } +} + static void ZEND_FASTCALL zend_jit_invalid_array_access(zval *container) { zend_error(E_WARNING, "Trying to access array offset on %s", zend_zval_value_name(container)); diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 3623689f05aae..57c0dedb2fa2d 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -26,6 +26,7 @@ #include "Zend/zend_constants.h" #include "Zend/Optimizer/zend_func_info.h" #include "Zend/Optimizer/zend_call_graph.h" +#include "zend_vm_opcodes.h" /* Address Encoding */ typedef uintptr_t zend_jit_addr; @@ -130,7 +131,7 @@ static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_ typedef struct _zend_jit_op_array_extension { zend_func_info func_info; const zend_op_array *op_array; - const void *orig_handler; + zend_vm_opcode_handler_t orig_handler; } zend_jit_op_array_extension; /* Profiler */ @@ -169,7 +170,7 @@ typedef struct _zend_jit_op_array_hot_extension { zend_func_info func_info; const zend_op_array *op_array; int16_t *counter; - const void *orig_handlers[1]; + zend_vm_opcode_handler_t orig_handlers[1]; } zend_jit_op_array_hot_extension; #define zend_jit_op_array_hash(op_array) \ @@ -196,10 +197,6 @@ extern const zend_op *zend_jit_halt_op; handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \ return; \ } while(0) -# define ZEND_OPCODE_TAIL_CALL_EX(handler, arg) do { \ - handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg); \ - return; \ - } while(0) # define ZEND_VM_ENTER_BIT 0 #else # define EXECUTE_DATA_D zend_execute_data* execute_data @@ -211,32 +208,38 @@ extern const zend_op *zend_jit_halt_op; # define OPLINE_DC , OPLINE_D # define OPLINE_CC , OPLINE_C # define ZEND_OPCODE_HANDLER_RET const zend_op * +# if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +# define ZEND_OPCODE_TAIL_CALL(handler) do { \ + ZEND_MUSTTAIL return (handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \ + } while(0) +# define ZEND_OPCODE_RETURN() ZEND_OPCODE_TAIL_CALL((zend_vm_opcode_handler_t)opline->handler) +# else +# define ZEND_OPCODE_TAIL_CALL(handler) do { \ + return handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \ + } while(0) +# define ZEND_OPCODE_RETURN() return opline +# endif # define ZEND_OPCODE_HANDLER_ARGS EXECUTE_DATA_D OPLINE_DC # define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU EXECUTE_DATA_C OPLINE_CC # define ZEND_OPCODE_HANDLER_ARGS_EX EXECUTE_DATA_D OPLINE_DC, # define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX EXECUTE_DATA_C OPLINE_CC, -# define ZEND_OPCODE_RETURN() return opline -# define ZEND_OPCODE_TAIL_CALL(handler) do { \ - return handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); \ - } while(0) -# define ZEND_OPCODE_TAIL_CALL_EX(handler, arg) do { \ - return handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX arg); \ - } while(0) # define ZEND_VM_ENTER_BIT 1ULL #endif -/* VM handlers */ -typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *zend_vm_opcode_handler_t)(ZEND_OPCODE_HANDLER_ARGS); - /* VM helpers */ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t call_info); ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t call_info); ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(ZEND_OPCODE_HANDLER_ARGS); +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_leave_func_helper_tailcall(ZEND_OPCODE_HANDLER_ARGS); +#endif -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_profile_helper(ZEND_OPCODE_HANDLER_ARGS); +#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_profile_helper(ZEND_OPCODE_HANDLER_ARGS); -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_HANDLER_ARGS); -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS); +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_func_counter_helper(ZEND_OPCODE_HANDLER_ARGS); +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS); +#endif ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_copy_extra_args_helper(ZEND_OPCODE_HANDLER_ARGS); ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_copy_extra_args_helper_no_skip_recv(ZEND_OPCODE_HANDLER_ARGS); @@ -339,8 +342,8 @@ typedef enum _zend_jit_trace_stop { typedef union _zend_op_trace_info { zend_op dummy; /* the size of this structure must be the same as zend_op */ struct { - const void *orig_handler; - const void *call_handler; + zend_vm_opcode_handler_t orig_handler; + zend_vm_opcode_handler_func_t call_handler; int16_t *counter; uint8_t trace_flags; }; @@ -668,9 +671,11 @@ struct _zend_jit_trace_stack_frame { (frame)->_info |= TRACE_FRAME_MASK_ALWAYS_RELEASE_THIS; \ } while (0) -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_trace_helper(ZEND_OPCODE_HANDLER_ARGS); -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_ret_trace_helper(ZEND_OPCODE_HANDLER_ARGS); -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS); +#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_func_trace_helper(ZEND_OPCODE_HANDLER_ARGS); +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_ret_trace_helper(ZEND_OPCODE_HANDLER_ARGS); +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS); +#endif int ZEND_FASTCALL zend_jit_trace_hot_root(zend_execute_data *execute_data, const zend_op *opline); zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *execute_data, diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 6aa7896554920..e0f8677f32889 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -16,8 +16,10 @@ * +----------------------------------------------------------------------+ */ +#include "Zend/zend_type_info.h" #include "jit/ir/ir.h" #include "jit/ir/ir_builder.h" +#include "jit/tls/zend_jit_tls.h" #if defined(IR_TARGET_X86) # define IR_REG_SP 4 /* IR_REG_RSP */ @@ -26,11 +28,21 @@ # define ZREG_IP 7 /* IR_REG_RDI */ # define ZREG_FIRST_FPR 8 # define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7)) /* all preserved registers */ +# if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +# error +# endif #elif defined(IR_TARGET_X64) # define IR_REG_SP 4 /* IR_REG_RSP */ # define IR_REG_FP 5 /* IR_REG_RBP */ -# define ZREG_FP 14 /* IR_REG_R14 */ -# define ZREG_IP 15 /* IR_REG_R15 */ +# if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +/* Use the first two arg registers of the preserve_none calling convention for FP/IP + * https://github.com/llvm/llvm-project/blob/68bfe91b5a34f80dbcc4f0a7fa5d7aa1cdf959c2/llvm/lib/Target/X86/X86CallingConv.td#L1029 */ +# define ZREG_FP 12 /* IR_REG_R12 */ +# define ZREG_IP 13 /* IR_REG_R13 */ +# else +# define ZREG_FP 14 /* IR_REG_R14 */ +# define ZREG_IP 15 /* IR_REG_R15 */ +# endif # define ZREG_FIRST_FPR 16 # if defined(_WIN64) # define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<6) | (1<<7) | (1<<12) | (1<<13) | (1<<14) | (1<<15)) @@ -45,9 +57,17 @@ # endif #elif defined(IR_TARGET_AARCH64) # define IR_REG_SP 31 /* IR_REG_RSP */ +# define IR_REG_LR 30 /* IR_REG_X30 */ # define IR_REG_FP 29 /* IR_REG_X29 */ -# define ZREG_FP 27 /* IR_REG_X27 */ -# define ZREG_IP 28 /* IR_REG_X28 */ +# if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +/* Use the first two arg registers of the preserve_none calling convention for FP/IP + * https://github.com/llvm/llvm-project/blob/68bfe91b5a34f80dbcc4f0a7fa5d7aa1cdf959c2/llvm/lib/Target/AArch64/AArch64CallingConvention.td#L541 */ +# define ZREG_FP 20 /* IR_REG_X20 */ +# define ZREG_IP 21 /* IR_REG_X21 */ +# else +# define ZREG_FP 27 /* IR_REG_X27 */ +# define ZREG_IP 28 /* IR_REG_X28 */ +# endif # define ZREG_FIRST_FPR 32 # define IR_REGSET_PRESERVED ((1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23) | \ (1<<24) | (1<<25) | (1<<26) | (1<<27) | (1<<28)) /* all preserved registers */ @@ -63,12 +83,22 @@ #undef _ir_CTX #define _ir_CTX (&jit->ctx) +#if GCC_GLOBAL_REGS +# define IR_OPCODE_HANDLER_RET IR_VOID +#else +# define IR_OPCODE_HANDLER_RET IR_ADDR +#endif + #undef ir_CONST_ADDR #define ir_CONST_ADDR(_addr) jit_CONST_ADDR(jit, (uintptr_t)(_addr)) #define ir_CONST_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), 0) #define ir_CONST_FC_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), IR_FASTCALL_FUNC) #define ir_CAST_FC_FUNC(_addr) ir_fold2(_ir_CTX, IR_OPT(IR_PROTO, IR_ADDR), (_addr), \ ir_proto_0(_ir_CTX, IR_FASTCALL_FUNC, IR_I32)) +# define ir_CONST_OPCODE_HANDLER_FUNC(_addr) \ + jit_CONST_OPCODE_HANDLER_FUNC(jit, _addr) +# define ir_CAST_OPCODE_HANDLER_FUNC(_addr) ir_fold2(_ir_CTX, IR_OPT(IR_PROTO, IR_ADDR), (_addr), \ + ir_proto_0(_ir_CTX, IR_FASTCALL_FUNC, IR_OPCODE_HANDLER_RET)) #define ir_CONST_FUNC_PROTO(_addr, _proto) \ jit_CONST_FUNC_PROTO(jit, (uintptr_t)(_addr), (_proto)) @@ -171,15 +201,9 @@ static uint32_t default_mflags = 0; static bool delayed_call_chain = 0; // TODO: remove this var (use jit->delayed_call_level) ??? #ifdef ZTS -# ifdef _WIN32 -extern uint32_t _tls_index; -extern char *_tls_start; -extern char *_tls_end; -# endif - static size_t tsrm_ls_cache_tcb_offset = 0; -static size_t tsrm_tls_index = 0; -static size_t tsrm_tls_offset = 0; +static size_t tsrm_tls_index = -1; +static size_t tsrm_tls_offset = -1; # define EG_TLS_OFFSET(field) \ (executor_globals_offset + offsetof(zend_executor_globals, field)) @@ -334,6 +358,8 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit, zend_jit_addr ref_addr, bool check_exception); +static ir_ref jit_CONST_FUNC(zend_jit_ctx *jit, uintptr_t addr, uint16_t flags); + typedef struct _zend_jit_stub { const char *name; int (*stub)(zend_jit_ctx *jit); @@ -463,6 +489,11 @@ static const char* zend_reg_name(int8_t reg) /* IR helpers */ #ifdef ZTS +static void * ZEND_FASTCALL zend_jit_get_tsrm_ls_cache(void) +{ + return _tsrm_ls_cache; +} + static ir_ref jit_TLS(zend_jit_ctx *jit) { ZEND_ASSERT(jit->ctx.control); @@ -482,9 +513,15 @@ static ir_ref jit_TLS(zend_jit_ctx *jit) ref = insn->op1; } } - jit->tls = ir_TLS( - tsrm_ls_cache_tcb_offset ? tsrm_ls_cache_tcb_offset : tsrm_tls_index, - tsrm_ls_cache_tcb_offset ? IR_NULL : tsrm_tls_offset); + + if (tsrm_ls_cache_tcb_offset == 0 && tsrm_tls_index == -1) { + jit->tls = ir_CALL(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_get_tsrm_ls_cache)); + } else { + jit->tls = ir_TLS( + tsrm_ls_cache_tcb_offset ? tsrm_ls_cache_tcb_offset : tsrm_tls_index, + tsrm_ls_cache_tcb_offset ? IR_NULL : tsrm_tls_offset); + } + return jit->tls; } #endif @@ -541,6 +578,11 @@ static ir_ref jit_CONST_FUNC(zend_jit_ctx *jit, uintptr_t addr, uint16_t flags) return jit_CONST_FUNC_PROTO(jit, addr, proto); } +static ir_ref jit_CONST_OPCODE_HANDLER_FUNC(zend_jit_ctx *jit, zend_vm_opcode_handler_t handler) +{ + return jit_CONST_FUNC(jit, (uintptr_t)handler, IR_FASTCALL_FUNC); +} + static ir_ref jit_ADD_OFFSET(zend_jit_ctx *jit, ir_ref addr, uintptr_t offset) { if (offset) { @@ -1914,24 +1956,36 @@ static void zend_jit_vm_leave(zend_jit_ctx *jit, ir_ref to_opline) ir_RETURN(ir_OR_A(to_opline, ir_CONST_ADDR(ZEND_VM_ENTER_BIT))); } +static void zend_jit_tailcall_handler(zend_jit_ctx *jit, ir_ref handler) +{ +#if defined(IR_TARGET_X86) + if (!IR_IS_CONST_REF(handler)) { + handler = ir_CAST_OPCODE_HANDLER_FUNC(handler); + } +#endif + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + ir_TAILCALL(IR_OPCODE_HANDLER_RET, handler); + } else { + ir_TAILCALL_2(IR_ADDR, handler, jit_FP(jit), jit_IP(jit)); + } +} + /* stubs */ static int zend_jit_exception_handler_stub(zend_jit_ctx *jit) { - const void *handler; - - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { - handler = zend_get_opcode_handler_func(EG(exception_op)); + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { + zend_vm_opcode_handler_func_t handler = (zend_vm_opcode_handler_func_t)zend_get_opcode_handler_func(EG(exception_op)); ir_CALL(IR_VOID, ir_CONST_FUNC(handler)); ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else { - handler = EG(exception_op)->handler; + zend_vm_opcode_handler_t handler = EG(exception_op)->handler; - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, ir_CONST_FUNC(handler)); + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, ir_CONST_OPCODE_HANDLER_FUNC(handler)); } else { - ir_ref ref = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + ir_ref ref = ir_CALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC(handler), jit_FP(jit), jit_IP(jit)); zend_jit_vm_enter(jit, ref); } } @@ -2030,8 +2084,8 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); } - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, ir_LOAD_A(jit_IP(jit))); } else { zend_jit_vm_enter(jit, jit_IP(jit)); } @@ -2040,12 +2094,16 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit) static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit) { +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + ir_TAILCALL(IR_OPCODE_HANDLER_RET, ir_CONST_OPCODE_HANDLER_FUNC(zend_jit_leave_func_helper_tailcall)); + return 1; +#else ir_ref call_info = ir_LOAD_U32(jit_EX(This.u1.type_info)); ir_ref if_top = ir_IF(ir_AND_U32(call_info, ir_CONST_U32(ZEND_CALL_TOP))); ir_IF_FALSE(if_top); - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_leave_nested_func_helper), call_info); jit_STORE_IP(jit, ir_LOAD_A(jit_EX(opline))); @@ -2058,7 +2116,7 @@ static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit) ir_IF_TRUE(if_top); - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_leave_top_func_helper), call_info); ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); } else if (GCC_GLOBAL_REGS) { @@ -2068,6 +2126,7 @@ static int zend_jit_leave_function_handler_stub(zend_jit_ctx *jit) } return 1; +#endif /* ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL */ } static int zend_jit_negative_shift_stub(zend_jit_ctx *jit) @@ -2228,7 +2287,7 @@ static int zend_jit_leave_throw_stub(zend_jit_ctx *jit) // JIT: opline = EG(exception_op); jit_STORE_IP(jit, jit_EG(exception_op)); - if (GCC_GLOBAL_REGS) { + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { ir_STORE(jit_EX(opline), jit_IP(jit)); // JIT: HANDLE_EXCEPTION() @@ -2242,11 +2301,11 @@ static int zend_jit_leave_throw_stub(zend_jit_ctx *jit) static int zend_jit_hybrid_runtime_jit_stub(zend_jit_ctx *jit) { - if (zend_jit_vm_kind != ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) { return 0; } - ir_CALL(IR_VOID, ir_CONST_FC_FUNC(zend_runtime_jit)); + ir_CALL(IR_VOID, ir_CONST_OPCODE_HANDLER_FUNC(zend_runtime_jit)); ir_IJMP(ir_LOAD_A(jit_IP(jit))); return 1; } @@ -2255,7 +2314,7 @@ static int zend_jit_hybrid_profile_jit_stub(zend_jit_ctx *jit) { ir_ref addr, func, run_time_cache, jit_extension; - if (zend_jit_vm_kind != ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) { return 0; } @@ -2311,7 +2370,7 @@ static int _zend_jit_hybrid_hot_counter_stub(zend_jit_ctx *jit, uint32_t cost) static int zend_jit_hybrid_func_hot_counter_stub(zend_jit_ctx *jit) { - if (zend_jit_vm_kind != ZEND_VM_KIND_HYBRID || !JIT_G(hot_func)) { + if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID || !JIT_G(hot_func)) { return 0; } @@ -2321,7 +2380,7 @@ static int zend_jit_hybrid_func_hot_counter_stub(zend_jit_ctx *jit) static int zend_jit_hybrid_loop_hot_counter_stub(zend_jit_ctx *jit) { - if (zend_jit_vm_kind != ZEND_VM_KIND_HYBRID || !JIT_G(hot_loop)) { + if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID || !JIT_G(hot_loop)) { return 0; } @@ -2376,14 +2435,14 @@ static int _zend_jit_hybrid_trace_counter_stub(zend_jit_ctx *jit, uint32_t cost) ir_IJMP(_zend_jit_orig_opline_handler(jit, offset)); ir_IF_TRUE(if_halt); - ir_IJMP(ir_CONST_FC_FUNC(zend_jit_halt_op->handler)); + ir_IJMP(ir_CONST_OPCODE_HANDLER_FUNC(zend_jit_halt_op->handler)); return 1; } static int zend_jit_hybrid_func_trace_counter_stub(zend_jit_ctx *jit) { - if (zend_jit_vm_kind != ZEND_VM_KIND_HYBRID || !JIT_G(hot_func)) { + if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID || !JIT_G(hot_func)) { return 0; } @@ -2393,7 +2452,7 @@ static int zend_jit_hybrid_func_trace_counter_stub(zend_jit_ctx *jit) static int zend_jit_hybrid_ret_trace_counter_stub(zend_jit_ctx *jit) { - if (zend_jit_vm_kind != ZEND_VM_KIND_HYBRID || !JIT_G(hot_return)) { + if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID || !JIT_G(hot_return)) { return 0; } @@ -2403,7 +2462,7 @@ static int zend_jit_hybrid_ret_trace_counter_stub(zend_jit_ctx *jit) static int zend_jit_hybrid_loop_trace_counter_stub(zend_jit_ctx *jit) { - if (zend_jit_vm_kind != ZEND_VM_KIND_HYBRID || !JIT_G(hot_loop)) { + if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID || !JIT_G(hot_loop)) { return 0; } @@ -2413,8 +2472,8 @@ static int zend_jit_hybrid_loop_trace_counter_stub(zend_jit_ctx *jit) static int zend_jit_trace_halt_stub(zend_jit_ctx *jit) { - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { - ir_TAILCALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_halt_op->handler)); + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { + ir_TAILCALL(IR_VOID, ir_CONST_OPCODE_HANDLER_FUNC(zend_jit_halt_op->handler)); } else if (GCC_GLOBAL_REGS) { jit_STORE_IP(jit, IR_NULL); ir_RETURN(IR_VOID); @@ -2426,8 +2485,8 @@ static int zend_jit_trace_halt_stub(zend_jit_ctx *jit) static int zend_jit_trace_escape_stub(zend_jit_ctx *jit) { - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, ir_LOAD_A(jit_IP(jit))); } else { zend_jit_vm_enter(jit, jit_IP(jit)); } @@ -2453,8 +2512,8 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) ref = ir_LOAD_A(jit_EX(opline)); jit_STORE_IP(jit, ref); - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, ir_LOAD_A(jit_IP(jit))); } else { zend_jit_vm_enter(jit, ref); } @@ -2473,11 +2532,11 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit) zend_jit_check_timeout(jit, NULL, NULL); addr = zend_jit_orig_opline_handler(jit); - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, addr); + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, addr); } else { #if defined(IR_TARGET_X86) - addr = ir_CAST_FC_FUNC(addr); + addr = ir_CAST_OPCODE_HANDLER_FUNC(addr); #endif ref = ir_CALL_2(IR_ADDR, addr, jit_FP(jit), jit_IP(jit)); zend_jit_vm_enter(jit, ref); @@ -2491,7 +2550,7 @@ static int zend_jit_undefined_offset_stub(zend_jit_ctx *jit) if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_long_key)); } else { - ir_TAILCALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_long_key), jit_FP(jit), jit_IP(jit)); + ir_TAILCALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_long_key), jit_FP(jit)); } return 1; @@ -2502,7 +2561,7 @@ static int zend_jit_undefined_key_stub(zend_jit_ctx *jit) if (GCC_GLOBAL_REGS) { ir_TAILCALL(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_string_key)); } else { - ir_TAILCALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_string_key), jit_FP(jit), jit_IP(jit)); + ir_TAILCALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_string_key), jit_FP(jit)); } return 1; @@ -2670,11 +2729,21 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags) jit->ctx.fixed_regset = (1<ctx.flags |= IR_NO_STACK_COMBINE; - if (zend_jit_vm_kind == ZEND_VM_KIND_CALL) { + if (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { jit->ctx.flags |= IR_FUNCTION; /* Stack must be 16 byte aligned */ /* TODO: select stack size ??? */ -#if defined(IR_TARGET_AARCH64) +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +# if defined(IR_TARGET_AARCH64) + /* Must save LR */ + jit->ctx.flags |= IR_USE_FRAME_POINTER; + /* Same as HYBRID VM */ + jit->ctx.fixed_stack_frame_size = sizeof(void*) * 4; /* 4 spill slots */ +# else + /* Same as HYBRID VM, plus 1 slot for re-alignment (caller pushes return address, frame is not aligned on entry) */ + jit->ctx.fixed_stack_frame_size = sizeof(void*) * 5; /* 5 spill slots (8 bytes) or 10 spill slots (4 bytes) */ +# endif +#elif defined(IR_TARGET_AARCH64) jit->ctx.flags |= IR_USE_FRAME_POINTER; jit->ctx.fixed_stack_frame_size = sizeof(void*) * 16; /* 10 saved registers and 6 spill slots (8 bytes) */ #elif defined(_WIN64) @@ -2690,6 +2759,23 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags) */ if (GCC_GLOBAL_REGS) { jit->ctx.fixed_save_regset = IR_REGSET_PRESERVED & ~((1<ctx.fixed_regset |= (1<ctx.fixed_regset |= (1<ctx.fixed_save_regset = IR_REGSET_PRESERVED; //#ifdef _WIN64 @@ -3127,6 +3213,8 @@ static void zend_jit_setup_disasm(void) REGISTER_DATA(EG(symbol_table)); REGISTER_DATA(CG(map_ptr_base)); +#else /* ZTS */ + REGISTER_HELPER(zend_jit_get_tsrm_ls_cache); #endif #endif } @@ -3138,13 +3226,15 @@ static void zend_jit_calc_trace_prologue_size(void) void *entry; size_t size; - zend_jit_init_ctx(jit, (zend_jit_vm_kind == ZEND_VM_KIND_CALL) ? 0 : IR_START_BR_TARGET); + zend_jit_init_ctx(jit, (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) ? 0 : IR_START_BR_TARGET); if (!GCC_GLOBAL_REGS) { - ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); - ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); - jit_STORE_FP(jit, execute_data_ref); - jit_STORE_IP(jit, opline_ref); + if (ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) { + ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); + ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); + jit_STORE_FP(jit, execute_data_ref); + jit_STORE_IP(jit, opline_ref); + } jit->ctx.flags |= IR_FASTCALL_FUNC; } @@ -3293,7 +3383,6 @@ static void zend_jit_setup_unwinder(void) } #endif - static void zend_jit_setup(bool reattached) { #if defined(IR_TARGET_X86) @@ -3312,170 +3401,21 @@ static void zend_jit_setup(bool reattached) } # endif #endif -#ifdef ZTS -#if defined(IR_TARGET_AARCH64) - tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset(); - -# ifdef __FreeBSD__ - if (tsrm_ls_cache_tcb_offset == 0) { - TLSDescriptor **where; - - __asm__( - "adrp %0, :tlsdesc:_tsrm_ls_cache\n" - "add %0, %0, :tlsdesc_lo12:_tsrm_ls_cache\n" - : "=r" (where)); - /* See https://github.com/ARM-software/abi-aa/blob/2a70c42d62e9c3eb5887fa50b71257f20daca6f9/aaelf64/aaelf64.rst - * section "Relocations for thread-local storage". - * The first entry holds a pointer to the variable's TLS descriptor resolver function and the second entry holds - * a platform-specific offset or pointer. */ - TLSDescriptor *tlsdesc = where[1]; - - tsrm_tls_offset = tlsdesc->offset; - /* Index is offset by 1 on FreeBSD (https://github.com/freebsd/freebsd-src/blob/22ca6db50f4e6bd75a141f57cf953d8de6531a06/lib/libc/gen/tls.c#L88) */ - tsrm_tls_index = (tlsdesc->index + 1) * 8; - } -# elif defined(__MUSL__) - if (tsrm_ls_cache_tcb_offset == 0) { - size_t **where; - - __asm__( - "adrp %0, :tlsdesc:_tsrm_ls_cache\n" - "add %0, %0, :tlsdesc_lo12:_tsrm_ls_cache\n" - : "=r" (where)); - /* See https://github.com/ARM-software/abi-aa/blob/2a70c42d62e9c3eb5887fa50b71257f20daca6f9/aaelf64/aaelf64.rst */ - size_t *tlsdesc = where[1]; - - tsrm_tls_offset = tlsdesc[1]; - tsrm_tls_index = tlsdesc[0] * 8; - } -# else - ZEND_ASSERT(tsrm_ls_cache_tcb_offset != 0); -# endif -# elif defined(_WIN64) - tsrm_tls_index = _tls_index * sizeof(void*); - - /* To find offset of "_tsrm_ls_cache" in TLS segment we perform a linear scan of local TLS memory */ - /* Probably, it might be better solution */ - do { - void ***tls_mem = ((void****)__readgsqword(0x58))[_tls_index]; - void *val = _tsrm_ls_cache; - size_t offset = 0; - size_t size = (char*)&_tls_end - (char*)&_tls_start; - - while (offset < size) { - if (*tls_mem == val) { - tsrm_tls_offset = offset; - break; - } - tls_mem++; - offset += sizeof(void*); - } - if (offset >= size) { - zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: offset >= size"); - } - } while(0); -# elif defined(ZEND_WIN32) - tsrm_tls_index = _tls_index * sizeof(void*); - - /* To find offset of "_tsrm_ls_cache" in TLS segment we perform a linear scan of local TLS memory */ - /* Probably, it might be better solution */ - do { - void ***tls_mem = ((void****)__readfsdword(0x2c))[_tls_index]; - void *val = _tsrm_ls_cache; - size_t offset = 0; - size_t size = (char*)&_tls_end - (char*)&_tls_start; - - while (offset < size) { - if (*tls_mem == val) { - tsrm_tls_offset = offset; - break; - } - tls_mem++; - offset += sizeof(void*); - } - if (offset >= size) { - zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Could not enable JIT: offset >= size"); - } - } while(0); -# elif defined(__APPLE__) && defined(__x86_64__) - tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset(); - if (tsrm_ls_cache_tcb_offset == 0) { - size_t *ti; - __asm__( - "leaq __tsrm_ls_cache(%%rip),%0" - : "=r" (ti)); - tsrm_tls_offset = ti[2]; - tsrm_tls_index = ti[1] * 8; - } -# elif defined(__GNUC__) && defined(__x86_64__) - tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset(); - if (tsrm_ls_cache_tcb_offset == 0) { -#if defined(__has_attribute) && __has_attribute(tls_model) && !defined(__FreeBSD__) && \ - !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__MUSL__) - size_t ret; - - asm ("movq _tsrm_ls_cache@gottpoff(%%rip),%0" - : "=r" (ret)); - tsrm_ls_cache_tcb_offset = ret; -#elif defined(__MUSL__) - size_t *ti; - - __asm__( - "leaq _tsrm_ls_cache@tlsgd(%%rip), %0\n" - : "=D" (ti)); - tsrm_tls_offset = ti[1]; - tsrm_tls_index = ti[0] * 8; -#elif defined(__FreeBSD__) - size_t *ti; - - __asm__( - "leaq _tsrm_ls_cache@tlsgd(%%rip), %0\n" - : "=D" (ti)); - tsrm_tls_offset = ti[1]; - /* Index is offset by 1 on FreeBSD (https://github.com/freebsd/freebsd-src/blob/bf56e8b9c8639ac4447d223b83cdc128107cc3cd/libexec/rtld-elf/rtld.c#L5260) */ - tsrm_tls_index = (ti[0] + 1) * 8; -#else - size_t *ti; - - __asm__( - "leaq _tsrm_ls_cache@tlsgd(%%rip), %0\n" - : "=D" (ti)); - tsrm_tls_offset = ti[1]; - tsrm_tls_index = ti[0] * 16; -#endif - } -# elif defined(__GNUC__) && defined(__i386__) - tsrm_ls_cache_tcb_offset = tsrm_get_ls_cache_tcb_offset(); - if (tsrm_ls_cache_tcb_offset == 0) { -#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__MUSL__) - size_t ret; - asm ("leal _tsrm_ls_cache@ntpoff,%0\n" - : "=a" (ret)); - tsrm_ls_cache_tcb_offset = ret; -#else - size_t *ti, _ebx, _ecx, _edx; - - __asm__( - "call 1f\n" - ".subsection 1\n" - "1:\tmovl (%%esp), %%ebx\n\t" - "ret\n" - ".previous\n\t" - "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" - "leal _tsrm_ls_cache@tlsldm(%%ebx), %0\n\t" - "call ___tls_get_addr@plt\n\t" - "leal _tsrm_ls_cache@tlsldm(%%ebx), %0\n" - : "=a" (ti), "=&b" (_ebx), "=&c" (_ecx), "=&d" (_edx)); - tsrm_tls_offset = ti[1]; - tsrm_tls_index = ti[0] * 8; -#endif +#ifdef ZTS + zend_result result = zend_jit_resolve_tsrm_ls_cache_offsets( + &tsrm_ls_cache_tcb_offset, + &tsrm_tls_index, + &tsrm_tls_offset + ); + if (result == FAILURE) { + zend_accel_error(ACCEL_LOG_INFO, + "Could not get _tsrm_ls_cache offsets, will fallback to runtime resolution"); } -# endif #endif #if !defined(ZEND_WIN32) && !defined(IR_TARGET_AARCH64) - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { zend_jit_set_sp_adj_vm(); // set zend_jit_hybrid_vm_sp_adj } #endif @@ -4125,7 +4065,7 @@ static void zend_jit_recv_entry(zend_jit_ctx *jit, int b) /* Insert a MERGE block with additional ENTRY input between predecessor and this one */ ir_ENTRY(ref, bb->start); - if (!GCC_GLOBAL_REGS) { + if (!GCC_GLOBAL_REGS && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) { /* 2 and 3 are hardcoded reference to IR_PARAMs */ ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM); ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1); @@ -4146,7 +4086,7 @@ static void zend_jit_osr_entry(zend_jit_ctx *jit, int b) /* Insert a MERGE block with additional ENTRY input between predecessor and this one */ ir_ENTRY(ref, bb->start); - if (!GCC_GLOBAL_REGS) { + if (!GCC_GLOBAL_REGS && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) { /* 2 and 3 are hardcoded reference to IR_PARAMs */ ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM); ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1); @@ -4162,7 +4102,7 @@ static void zend_jit_osr_entry(zend_jit_ctx *jit, int b) static ir_ref zend_jit_continue_entry(zend_jit_ctx *jit, ir_ref src, unsigned int label) { ir_ENTRY(src, label); - if (!GCC_GLOBAL_REGS) { + if (!GCC_GLOBAL_REGS && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) { /* 2 and 3 are hardcoded reference to IR_PARAMs */ ZEND_ASSERT(jit->ctx.ir_base[2].op == IR_PARAM); ZEND_ASSERT(jit->ctx.ir_base[2].op3 == 1); @@ -4176,17 +4116,16 @@ static ir_ref zend_jit_continue_entry(zend_jit_ctx *jit, ir_ref src, unsigned in static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_throw) { - const void *handler; - zend_jit_set_ip(jit, opline); - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { - handler = zend_get_opcode_handler_func(opline); - } else { - handler = opline->handler; - } if (GCC_GLOBAL_REGS) { + zend_vm_opcode_handler_func_t handler = (zend_vm_opcode_handler_func_t)zend_get_opcode_handler_func(opline); ir_CALL(IR_VOID, ir_CONST_FUNC(handler)); + } else if (ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_vm_opcode_handler_func_t handler = (zend_vm_opcode_handler_func_t)zend_get_opcode_handler_func(opline); + ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + jit_STORE_IP(jit, ip); } else { + zend_vm_opcode_handler_t handler = opline->handler; ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); jit_STORE_IP(jit, ip); } @@ -4216,30 +4155,29 @@ static int zend_jit_handler(zend_jit_ctx *jit, const zend_op *opline, int may_th static int zend_jit_tail_handler(zend_jit_ctx *jit, const zend_op *opline) { - const void *handler; ir_ref ref; zend_basic_block *bb; zend_jit_set_ip(jit, opline); - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { if (opline->opcode == ZEND_DO_UCALL || opline->opcode == ZEND_DO_FCALL_BY_NAME || opline->opcode == ZEND_DO_FCALL || opline->opcode == ZEND_RETURN) { /* Use inlined HYBRID VM handler */ - handler = opline->handler; + zend_vm_opcode_handler_t handler = opline->handler; ir_TAILCALL(IR_VOID, ir_CONST_FUNC(handler)); } else { - handler = zend_get_opcode_handler_func(opline); + zend_vm_opcode_handler_func_t handler = (zend_vm_opcode_handler_func_t)zend_get_opcode_handler_func(opline); ir_CALL(IR_VOID, ir_CONST_FUNC(handler)); ref = ir_LOAD_A(jit_IP(jit)); ir_TAILCALL(IR_VOID, ref); } } else { - handler = opline->handler; - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, ir_CONST_FUNC(handler)); + zend_vm_opcode_handler_t handler = opline->handler; + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, ir_CONST_OPCODE_HANDLER_FUNC(handler)); } else if ((jit->ssa->cfg.flags & ZEND_FUNC_RECURSIVE_DIRECTLY) && (opline->opcode == ZEND_CATCH || opline->opcode == ZEND_FAST_CALL @@ -4247,10 +4185,10 @@ static int zend_jit_tail_handler(zend_jit_ctx *jit, const zend_op *opline) || opline->opcode == ZEND_MATCH_ERROR || opline->opcode == ZEND_THROW || opline->opcode == ZEND_VERIFY_NEVER_TYPE)) { - ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC(handler), jit_FP(jit), jit_IP(jit)); zend_jit_vm_enter(jit, ip); } else { - ir_TAILCALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit)); + ir_TAILCALL_2(IR_ADDR, ir_CONST_OPCODE_HANDLER_FUNC(handler), jit_FP(jit), jit_IP(jit)); } } if (jit->b >= 0) { @@ -4325,6 +4263,11 @@ static int zend_jit_spill_store_inv(zend_jit_ctx *jit, zend_jit_addr src, zend_j ZEND_ASSERT(Z_MODE(src) == IS_REG); ZEND_ASSERT(Z_MODE(dst) == IS_MEM_ZVAL); + if (Z_LOAD(src) || Z_STORE(src)) { + /* it's not necessary to store register if it was previously loaded or already stored */ + return 1; + } + if ((info & MAY_BE_ANY) == MAY_BE_LONG) { jit_set_Z_LVAL(jit, dst, zend_jit_use_reg(jit, src)); if (Z_REG(dst) != ZREG_FP || !JIT_G(current_frame)) { @@ -4865,33 +4808,30 @@ static int zend_jit_inc_dec(zend_jit_ctx *jit, const zend_op *opline, uint32_t o int32_t exit_point; const void *exit_addr; zend_jit_trace_stack *stack; - uint32_t old_res_info = 0; + uint32_t old_res_info = 0, old_op1_info = 0; stack = JIT_G(current_frame)->stack; if (opline->result_type != IS_UNUSED) { old_res_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var)); + SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_LONG, 0); if (opline->opcode == ZEND_PRE_INC || opline->opcode == ZEND_PRE_DEC) { - SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_LONG, 0); + SET_STACK_REF(stack, EX_VAR_TO_NUM(opline->result.var), ref); + } else { + SET_STACK_REF(stack, EX_VAR_TO_NUM(opline->result.var), op1_lval_ref); } } + old_op1_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var)); + SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), IS_LONG, 0); + SET_STACK_REF(stack, EX_VAR_TO_NUM(opline->op1.var), ref); + exit_point = zend_jit_trace_get_exit_point(opline + 1, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); - if ((opline->opcode == ZEND_PRE_INC || opline->opcode == ZEND_PRE_DEC) && - opline->result_type != IS_UNUSED) { - if_overflow = ir_IF(ir_OVERFLOW(ref)); - ir_IF_FALSE_cold(if_overflow); - jit_set_Z_LVAL(jit, res_addr, ref); - if (Z_MODE(res_addr) != IS_REG) { - jit_set_Z_TYPE_INFO(jit, res_addr, IS_LONG); - } - jit_SIDE_EXIT(jit, ir_CONST_ADDR(exit_addr)); - ir_IF_TRUE(if_overflow); - } else { - ir_GUARD(ir_OVERFLOW(ref), ir_CONST_ADDR(exit_addr)); - } + ir_GUARD(ir_OVERFLOW(ref), ir_CONST_ADDR(exit_addr)); + if (opline->result_type != IS_UNUSED) { SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_res_info); } + SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var), old_op1_info); } else { if_overflow = ir_IF(ir_OVERFLOW(ref)); ir_IF_FALSE(if_overflow); @@ -10348,6 +10288,8 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen } if (GCC_GLOBAL_REGS) { ir_CALL(IR_VOID, helper); + } else if (ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + ir_CALL_2(IR_ADDR, helper, jit_FP(jit), jit_IP(jit)); } else { ir_ref ref = ir_CALL_2(IR_ADDR, helper, jit_FP(jit), jit_IP(jit)); jit_STORE_IP(jit, ref); @@ -10522,8 +10464,8 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen } } /* fallback to indirect JMP or RETURN */ - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, ir_LOAD_A(jit_IP(jit))); } else { zend_jit_vm_enter(jit, jit_IP(jit)); } @@ -11132,7 +11074,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, if (may_be_top_frame) { // TODO: try to avoid this check ??? - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { #if 0 /* this check should be handled by the following OPLINE guard */ | cmp IP, zend_jit_halt_op @@ -11290,8 +11232,8 @@ static int zend_jit_leave_func(zend_jit_ctx *jit, jit_STORE_IP(jit, ir_ADD_OFFSET(jit_IP(jit), sizeof(zend_op))); } - if (GCC_GLOBAL_REGS) { - ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { + zend_jit_tailcall_handler(jit, ir_LOAD_A(jit_IP(jit))); } else { zend_jit_vm_leave(jit, jit_IP(jit)); } @@ -12850,7 +12792,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, } } - if (opline->opcode != ZEND_FETCH_DIM_IS && opline->opcode != ZEND_FETCH_LIST_R) { + if (opline->opcode != ZEND_FETCH_DIM_IS) { ir_ref ref; may_throw = 1; @@ -12860,7 +12802,11 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, jit_SET_EX_OPLINE(jit, opline); ref = jit_ZVAL_ADDR(jit, op1_addr); } - ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_invalid_array_access), ref); + if (opline->opcode == ZEND_FETCH_LIST_R) { + ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_invalid_array_use), ref); + } else { + ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_invalid_array_access), ref); + } } jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); @@ -14806,6 +14752,13 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit, ir_ref slow_inputs = IR_UNUSED; uint32_t res_info = RES_INFO(); + if (Z_MODE(val_addr) == IS_REG + && Z_LOAD(val_addr) + && jit->ra[Z_SSA_VAR(val_addr)].ref == IR_NULL) { + /* Force load */ + zend_jit_use_reg(jit, val_addr); + } + if (val_addr != val_def_addr && val_def_addr) { if (!zend_jit_update_regs(jit, (opline+1)->op1.var, val_addr, val_def_addr, val_info)) { return 0; @@ -16714,7 +16667,7 @@ static int zend_jit_start(zend_jit_ctx *jit, const zend_op_array *op_array, zend int i, count; zend_basic_block *bb; - zend_jit_init_ctx(jit, (zend_jit_vm_kind == ZEND_VM_KIND_CALL) ? 0 : (IR_START_BR_TARGET|IR_ENTRY_BR_TARGET)); + zend_jit_init_ctx(jit, (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) ? 0 : (IR_START_BR_TARGET|IR_ENTRY_BR_TARGET)); jit->ctx.spill_base = ZREG_FP; @@ -16731,17 +16684,19 @@ static int zend_jit_start(zend_jit_ctx *jit, const zend_op_array *op_array, zend jit->bb_edges = zend_arena_calloc(&CG(arena), count, sizeof(ir_ref)); if (!GCC_GLOBAL_REGS) { - ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); - ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); - jit_STORE_FP(jit, execute_data_ref); - jit_STORE_IP(jit, opline_ref); + if (ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) { + ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); + ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); + jit_STORE_FP(jit, execute_data_ref); + jit_STORE_IP(jit, opline_ref); + } jit->ctx.flags |= IR_FASTCALL_FUNC; } return 1; } -static void *zend_jit_finish(zend_jit_ctx *jit) +static zend_vm_opcode_handler_t zend_jit_finish(zend_jit_ctx *jit) { void *entry; size_t size; @@ -16792,7 +16747,7 @@ static void *zend_jit_finish(zend_jit_ctx *jit) // ir_mem_unprotect(entry, size); if (!(jit->ctx.flags & IR_FUNCTION) - && zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { + && ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { #if !defined(ZEND_WIN32) && !defined(IR_TARGET_AARCH64) sp_offset = zend_jit_hybrid_vm_sp_adj; #else @@ -16825,14 +16780,14 @@ static void *zend_jit_finish(zend_jit_ctx *jit) opline++; } } - opline->handler = entry; + opline->handler = (zend_vm_opcode_handler_t)entry; if (jit->ctx.entries_count) { /* For all entries */ int i = jit->ctx.entries_count; do { ir_insn *insn = &jit->ctx.ir_base[jit->ctx.entries[--i]]; - op_array->opcodes[insn->op2].handler = (char*)entry + insn->op3; + op_array->opcodes[insn->op2].handler = (zend_vm_opcode_handler_t)((char*)entry + insn->op3); } while (i != 0); } } else { @@ -16859,7 +16814,7 @@ static void *zend_jit_finish(zend_jit_ctx *jit) zend_string_release(str); } - return entry; + return (zend_vm_opcode_handler_t)entry; } static const void *zend_jit_trace_allocate_exit_group(uint32_t n) @@ -17109,8 +17064,8 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr zend_jit_op_array_trace_extension *jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array); size_t offset = jit_extension->offset; - const void *handler = - (zend_vm_opcode_handler_t)ZEND_OP_TRACE_INFO(opline, offset)->call_handler; + zend_vm_opcode_handler_func_t handler = + ZEND_OP_TRACE_INFO(opline, offset)->call_handler; ir_ref ref; zend_jit_set_ip(jit, opline); @@ -17123,7 +17078,8 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr opline->opcode == ZEND_DO_UCALL || opline->opcode == ZEND_DO_FCALL_BY_NAME || opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_GENERATOR_CREATE) { + opline->opcode == ZEND_GENERATOR_CREATE || + opline->opcode == ZEND_INCLUDE_OR_EVAL) { jit_STORE_IP(jit, ir_AND_A(ref, ir_CONST_ADDR(~ZEND_VM_ENTER_BIT))); } else { @@ -17140,14 +17096,16 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr trace++; } - if (!GCC_GLOBAL_REGS - && (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_RETURN)) { + if ((!GCC_GLOBAL_REGS + && (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_RETURN)) + || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { if (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF || opline->opcode == ZEND_DO_UCALL || opline->opcode == ZEND_DO_FCALL_BY_NAME || opline->opcode == ZEND_DO_FCALL || - opline->opcode == ZEND_GENERATOR_CREATE) { + opline->opcode == ZEND_GENERATOR_CREATE || + opline->opcode == ZEND_INCLUDE_OR_EVAL) { ir_ref addr = jit_EG(current_execute_data); @@ -17160,7 +17118,7 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr opline->opcode == ZEND_RETURN_BY_REF || opline->opcode == ZEND_GENERATOR_CREATE) { - if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) { + if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) { if (trace->op != ZEND_JIT_TRACE_END || (trace->stop != ZEND_JIT_TRACE_STOP_RETURN && trace->stop < ZEND_JIT_TRACE_STOP_INTERPRETER)) { @@ -17274,7 +17232,7 @@ static int zend_jit_deoptimizer_start(zend_jit_ctx *jit, uint32_t trace_num, uint32_t exit_num) { - zend_jit_init_ctx(jit, (zend_jit_vm_kind == ZEND_VM_KIND_CALL) ? 0 : IR_START_BR_TARGET); + zend_jit_init_ctx(jit, (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) ? 0 : IR_START_BR_TARGET); jit->ctx.spill_base = ZREG_FP; @@ -17295,7 +17253,7 @@ static int zend_jit_trace_start(zend_jit_ctx *jit, zend_jit_trace_info *parent, uint32_t exit_num) { - zend_jit_init_ctx(jit, (zend_jit_vm_kind == ZEND_VM_KIND_CALL) ? 0 : IR_START_BR_TARGET); + zend_jit_init_ctx(jit, (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) ? 0 : IR_START_BR_TARGET); jit->ctx.spill_base = ZREG_FP; @@ -17306,10 +17264,12 @@ static int zend_jit_trace_start(zend_jit_ctx *jit, if (!GCC_GLOBAL_REGS) { if (!parent) { - ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); - ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); - jit_STORE_FP(jit, execute_data_ref); - jit_STORE_IP(jit, opline_ref); + if (ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL) { + ir_ref execute_data_ref = ir_PARAM(IR_ADDR, "execute_data", 1); + ir_ref opline_ref = ir_PARAM(IR_ADDR, "opline", 2); + jit_STORE_FP(jit, execute_data_ref); + jit_STORE_IP(jit, opline_ref); + } jit->ctx.flags |= IR_FASTCALL_FUNC; } } @@ -17412,11 +17372,11 @@ static int zend_jit_trace_end_loop(zend_jit_ctx *jit, int loop_ref, const void * static int zend_jit_trace_return(zend_jit_ctx *jit, bool original_handler, const zend_op *opline) { - if (GCC_GLOBAL_REGS) { + if (GCC_GLOBAL_REGS || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL) { if (!original_handler) { - ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit))); + zend_jit_tailcall_handler(jit, ir_LOAD_A(jit_IP(jit))); } else { - ir_TAILCALL(IR_VOID, zend_jit_orig_opline_handler(jit)); + zend_jit_tailcall_handler(jit, zend_jit_orig_opline_handler(jit)); } } else { if (original_handler) { @@ -17427,16 +17387,8 @@ static int zend_jit_trace_return(zend_jit_ctx *jit, bool original_handler, const addr = ir_CAST_FC_FUNC(addr); #endif ref = ir_CALL_2(IR_ADDR, addr, jit_FP(jit), jit_IP(jit)); - if (opline && - (opline->opcode == ZEND_RETURN - || opline->opcode == ZEND_RETURN_BY_REF - || opline->opcode == ZEND_GENERATOR_RETURN - || opline->opcode == ZEND_GENERATOR_CREATE - || opline->opcode == ZEND_YIELD - || opline->opcode == ZEND_YIELD_FROM)) { - zend_jit_vm_enter(jit, ref); - return 1; - } + zend_jit_vm_enter(jit, ref); + return 1; } zend_jit_vm_enter(jit, jit_IP(jit)); } diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index aeec674d60f3e..66bb380c23d8d 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -20,6 +20,7 @@ #include "zend_jit_internal.h" #include "zend_shared_alloc.h" #include "ir/ir.h" +#include "zend_vm_opcodes.h" static zend_jit_trace_info *zend_jit_traces = NULL; static const void **zend_jit_exit_groups = NULL; @@ -3409,7 +3410,7 @@ static void zend_jit_trace_setup_ret_counter(const zend_op *opline, size_t offse ZEND_JIT_COUNTER_NUM = (ZEND_JIT_COUNTER_NUM + 1) % ZEND_HOT_COUNTERS_COUNT; } ZEND_OP_TRACE_INFO(next_opline, offset)->trace_flags = ZEND_JIT_TRACE_START_RETURN; - next_opline->handler = (const void*)zend_jit_ret_trace_counter_handler; + next_opline->handler = zend_jit_ret_trace_counter_handler; } } @@ -4079,9 +4080,9 @@ static bool zend_jit_trace_may_throw(const zend_op *opline, return zend_may_throw_ex(opline, ssa_op, op_array, ssa, t1, t2); } -static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t parent_trace, uint32_t exit_num) +static zend_vm_opcode_handler_t zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t parent_trace, uint32_t exit_num) { - const void *handler = NULL; + zend_vm_opcode_handler_t handler = NULL; zend_jit_ctx ctx; zend_jit_ctx *jit = &ctx; zend_jit_reg_var *ra = NULL; @@ -4094,6 +4095,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par zend_jit_trace_rec *p; zend_jit_op_array_trace_extension *jit_extension; int num_op_arrays = 0; + bool do_bailout = 0; zend_jit_trace_info *t; const zend_op_array *op_arrays[ZEND_JIT_TRACE_MAX_FUNCS]; uint8_t smart_branch_opcode; @@ -4124,6 +4126,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par checkpoint = zend_arena_checkpoint(CG(arena)); + zend_try { + ssa = zend_jit_trace_build_tssa(trace_buffer, parent_trace, exit_num, script, op_arrays, &num_op_arrays); if (!ssa) { @@ -7357,6 +7361,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par zend_string_release(name); } + } zend_catch { + do_bailout = 1; + } zend_end_try(); + jit_cleanup: /* Clean up used op_arrays */ while (num_op_arrays > 0) { @@ -7377,6 +7385,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par JIT_G(current_frame) = NULL; JIT_G(current_trace) = NULL; + if (do_bailout) { + zend_bailout(); + } + return handler; } @@ -7392,9 +7404,9 @@ static zend_string *zend_jit_trace_escape_name(uint32_t trace_num, uint32_t exit return buf.s; } -static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_num) +static zend_vm_opcode_handler_t zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_num) { - const void *handler = NULL; + zend_vm_opcode_handler_t handler = NULL; zend_jit_ctx ctx; zend_string *name; void *checkpoint; @@ -7458,7 +7470,7 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace_buffer, const zend_op *opline, size_t offset) { zend_jit_trace_stop ret; - const void *handler; + zend_vm_opcode_handler_t handler; uint8_t orig_trigger; zend_jit_trace_info *t = NULL; zend_jit_trace_exit_info exit_info[ZEND_JIT_TRACE_MAX_EXITS]; @@ -8832,11 +8844,11 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf zend_jit_unprotect(); if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_LOOP) { - ((zend_op*)(t->opline))->handler = (const void*)zend_jit_loop_trace_counter_handler; + ((zend_op*)(t->opline))->handler = zend_jit_loop_trace_counter_handler; } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_ENTER) { - ((zend_op*)(t->opline))->handler = (const void*)zend_jit_func_trace_counter_handler; + ((zend_op*)(t->opline))->handler = zend_jit_func_trace_counter_handler; } else if (ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_START_RETURN) { - ((zend_op*)(t->opline))->handler = (const void*)zend_jit_ret_trace_counter_handler; + ((zend_op*)(t->opline))->handler = zend_jit_ret_trace_counter_handler; } ZEND_OP_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags &= ZEND_JIT_TRACE_START_LOOP|ZEND_JIT_TRACE_START_ENTER|ZEND_JIT_TRACE_START_RETURN; @@ -8889,9 +8901,9 @@ static int zend_jit_restart_hot_trace_counters(zend_op_array *op_array) jit_extension->trace_info[i].trace_flags &= ZEND_JIT_TRACE_START_LOOP | ZEND_JIT_TRACE_START_ENTER | ZEND_JIT_TRACE_UNSUPPORTED; if (jit_extension->trace_info[i].trace_flags == ZEND_JIT_TRACE_START_LOOP) { - op_array->opcodes[i].handler = (const void*)zend_jit_loop_trace_counter_handler; + op_array->opcodes[i].handler = zend_jit_loop_trace_counter_handler; } else if (jit_extension->trace_info[i].trace_flags == ZEND_JIT_TRACE_START_ENTER) { - op_array->opcodes[i].handler = (const void*)zend_jit_func_trace_counter_handler; + op_array->opcodes[i].handler = zend_jit_func_trace_counter_handler; } else { op_array->opcodes[i].handler = jit_extension->trace_info[i].orig_handler; } @@ -8917,7 +8929,7 @@ static int zend_jit_setup_hot_trace_counters(zend_op_array *op_array) jit_extension->offset = (char*)jit_extension->trace_info - (char*)op_array->opcodes; for (i = 0; i < op_array->last; i++) { jit_extension->trace_info[i].orig_handler = op_array->opcodes[i].handler; - jit_extension->trace_info[i].call_handler = zend_get_opcode_handler_func(&op_array->opcodes[i]); + jit_extension->trace_info[i].call_handler = (zend_vm_opcode_handler_func_t)zend_get_opcode_handler_func(&op_array->opcodes[i]); jit_extension->trace_info[i].counter = NULL; jit_extension->trace_info[i].trace_flags = zend_jit_trace_supported(&op_array->opcodes[i]); @@ -8939,7 +8951,7 @@ static int zend_jit_setup_hot_trace_counters(zend_op_array *op_array) /* loop header */ opline = op_array->opcodes + cfg.blocks[i].start; if (!(ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->trace_flags & ZEND_JIT_TRACE_UNSUPPORTED)) { - opline->handler = (const void*)zend_jit_loop_trace_counter_handler; + opline->handler = zend_jit_loop_trace_counter_handler; if (!ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->counter) { ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->counter = &zend_jit_hot_counters[ZEND_JIT_COUNTER_NUM]; @@ -8964,7 +8976,7 @@ static int zend_jit_setup_hot_trace_counters(zend_op_array *op_array) if (!ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->trace_flags) { /* function entry */ - opline->handler = (const void*)zend_jit_func_trace_counter_handler; + opline->handler = zend_jit_func_trace_counter_handler; ZEND_OP_TRACE_INFO(opline, jit_extension->offset)->counter = &zend_jit_hot_counters[ZEND_JIT_COUNTER_NUM]; ZEND_JIT_COUNTER_NUM = (ZEND_JIT_COUNTER_NUM + 1) % ZEND_HOT_COUNTERS_COUNT; diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 4348fbd53ad48..cb896c0cd8c6f 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -46,6 +46,60 @@ register const zend_op* volatile opline __asm__("x28"); # pragma GCC diagnostic warning "-Wvolatile-register-var" #endif +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_leave_func_helper_tailcall(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_execute_data *old_execute_data; + uint32_t call_info = EX_CALL_INFO(); + + if (!(call_info & ZEND_CALL_TOP)) { + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + + zend_vm_stack_free_extra_args_ex(call_info, execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + OBJ_RELEASE(Z_OBJ(execute_data->This)); + } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); + } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } + + old_execute_data = execute_data; + execute_data = EX(prev_execute_data); + zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + + if (UNEXPECTED(EG(exception) != NULL)) { + const zend_op *old_opline = EX(opline); + zend_throw_exception_internal(NULL); + if (old_opline->result_type != IS_UNDEF) { + zval_ptr_dtor(EX_VAR(old_opline->result.var)); + } + opline = EG(current_execute_data)->opline; + } else { + opline = ++EX(opline); + } + ZEND_OPCODE_TAIL_CALL(opline->handler); + } else { + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + zend_vm_stack_free_extra_args_ex(call_info, execute_data); + } + if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { + zend_free_extra_named_params(EX(extra_named_params)); + } + if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); + } + return (zend_op*)ZEND_VM_ENTER_BIT; + } +} +#endif + ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t call_info) { zend_execute_data *old_execute_data; @@ -75,14 +129,16 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPC zval_ptr_dtor(EX_VAR(old_opline->result.var)); } #ifndef HAVE_GCC_GLOBAL_REGS - return (zend_op*)((uintptr_t)EG(current_execute_data)->opline | ZEND_VM_ENTER_BIT); + return EG(current_execute_data)->opline; #endif } else { EX(opline)++; #ifdef HAVE_GCC_GLOBAL_REGS opline = EX(opline); +#elif ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + return EX(opline); #else - return (zend_op*)((uintptr_t)EX(opline) | ZEND_VM_ENTER_BIT); + return (const zend_op*)((uintptr_t)EX(opline) | ZEND_VM_ENTER_BIT); #endif } } @@ -101,11 +157,11 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(ZEND_OPCODE if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); } - execute_data = EG(current_execute_data); #ifdef HAVE_GCC_GLOBAL_REGS + execute_data = EG(current_execute_data); opline = zend_jit_halt_op; #else - return (const zend_op*)ZEND_VM_ENTER_BIT; // ZEND_VM_RETURN + return (const zend_op*)ZEND_VM_ENTER_BIT; #endif } @@ -114,9 +170,9 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_func_helper(ZEND_OPCODE_HAN uint32_t call_info = EX_CALL_INFO(); if (call_info & ZEND_CALL_TOP) { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_leave_top_func_helper, call_info); + return zend_jit_leave_top_func_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX call_info); } else { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_leave_nested_func_helper, call_info); + return zend_jit_leave_nested_func_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX call_info); } } @@ -298,17 +354,18 @@ void ZEND_FASTCALL zend_jit_undefined_string_key(EXECUTE_DATA_D) ZVAL_NULL(result); } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_profile_helper(ZEND_OPCODE_HANDLER_ARGS) +#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_profile_helper(ZEND_OPCODE_HANDLER_ARGS) { zend_op_array *op_array = (zend_op_array*)EX(func); zend_jit_op_array_extension *jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array); - zend_vm_opcode_handler_t handler = (zend_vm_opcode_handler_t) jit_extension->orig_handler; + zend_vm_opcode_handler_t handler = jit_extension->orig_handler; ++*(uintptr_t*)(EX(run_time_cache) + zend_jit_profile_counter_rid); ++zend_jit_profile_counter; ZEND_OPCODE_TAIL_CALL(handler); } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_HANDLER_ARGS) +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_func_counter_helper(ZEND_OPCODE_HANDLER_ARGS) { zend_jit_op_array_hot_extension *jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); @@ -325,7 +382,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_H } } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS) +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS) { zend_jit_op_array_hot_extension *jit_extension = (zend_jit_op_array_hot_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); @@ -337,10 +394,11 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_H zend_jit_hot_func(execute_data, opline); ZEND_OPCODE_RETURN(); } else { - zend_vm_opcode_handler_t handler = (zend_vm_opcode_handler_t)jit_extension->orig_handlers[opline - EX(func)->op_array.opcodes]; + zend_vm_opcode_handler_t handler = jit_extension->orig_handlers[opline - EX(func)->op_array.opcodes]; ZEND_OPCODE_TAIL_CALL(handler); } } +#endif static zend_always_inline zend_constant* _zend_quick_get_constant( const zval *key, uint32_t flags, int check_defined_only) @@ -402,14 +460,13 @@ zend_constant* ZEND_FASTCALL zend_jit_check_constant(const zval *key) return _zend_quick_get_constant(key, 0, 1); } -static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_counter_helper(ZEND_OPCODE_HANDLER_ARGS_EX uint32_t cost) +#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_trace_counter_helper(ZEND_OPCODE_HANDLER_ARGS) { zend_jit_op_array_trace_extension *jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); size_t offset = jit_extension->offset; - *(ZEND_OP_TRACE_INFO(opline, offset)->counter) -= cost; - if (UNEXPECTED(*(ZEND_OP_TRACE_INFO(opline, offset)->counter) <= 0)) { *(ZEND_OP_TRACE_INFO(opline, offset)->counter) = ZEND_JIT_COUNTER_INIT; if (UNEXPECTED(zend_jit_trace_hot_root(execute_data, opline) < 0)) { @@ -424,32 +481,57 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_c opline = execute_data ? EX(opline) : NULL; #ifdef HAVE_GCC_GLOBAL_REGS return; +#elif ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL + if (EXPECTED(opline)) { + ZEND_OPCODE_TAIL_CALL((zend_vm_opcode_handler_t)opline->handler); + } else { + return (const zend_op*)ZEND_VM_ENTER_BIT; + } #else return (const zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT); // ZEND_VM_ENTER() / ZEND_VM_RETURN() #endif } else { - zend_vm_opcode_handler_t handler = (zend_vm_opcode_handler_t)ZEND_OP_TRACE_INFO(opline, offset)->orig_handler; + zend_vm_opcode_handler_t handler = ZEND_OP_TRACE_INFO(opline, offset)->orig_handler; ZEND_OPCODE_TAIL_CALL(handler); } } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_trace_helper(ZEND_OPCODE_HANDLER_ARGS) +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_func_trace_helper(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, - ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_func) - 1) / JIT_G(hot_func))); + zend_jit_op_array_trace_extension *jit_extension = + (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); + size_t offset = jit_extension->offset; + uint32_t cost = ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_func) - 1) / JIT_G(hot_func)); + + *(ZEND_OP_TRACE_INFO(opline, offset)->counter) -= cost; + + ZEND_OPCODE_TAIL_CALL(zend_jit_trace_counter_helper); } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_ret_trace_helper(ZEND_OPCODE_HANDLER_ARGS) +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_ret_trace_helper(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, - ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_return) - 1) / JIT_G(hot_return))); + zend_jit_op_array_trace_extension *jit_extension = + (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); + size_t offset = jit_extension->offset; + uint32_t cost = ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_return) - 1) / JIT_G(hot_return)); + + *(ZEND_OP_TRACE_INFO(opline, offset)->counter) -= cost; + + ZEND_OPCODE_TAIL_CALL(zend_jit_trace_counter_helper); } -ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS) +ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_jit_loop_trace_helper(ZEND_OPCODE_HANDLER_ARGS) { - ZEND_OPCODE_TAIL_CALL_EX(zend_jit_trace_counter_helper, - ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_loop) - 1) / JIT_G(hot_loop))); + zend_jit_op_array_trace_extension *jit_extension = + (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(&EX(func)->op_array); + size_t offset = jit_extension->offset; + uint32_t cost = ((ZEND_JIT_COUNTER_INIT + JIT_G(hot_loop) - 1) / JIT_G(hot_loop)); + + *(ZEND_OP_TRACE_INFO(opline, offset)->counter) -= cost; + + ZEND_OPCODE_TAIL_CALL(zend_jit_trace_counter_helper); } +#endif #define TRACE_RECORD(_op, _info, _ptr) \ trace_buffer[idx].info = _op | (_info); \ @@ -657,7 +739,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, zend_jit_trace_stop halt = 0; int level = 0; int ret_level = 0; - zend_vm_opcode_handler_t handler; + zend_vm_opcode_handler_func_t handler; const zend_op_array *op_array; zend_jit_op_array_trace_extension *jit_extension; size_t offset; @@ -983,7 +1065,8 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, break; } - handler = (zend_vm_opcode_handler_t)ZEND_OP_TRACE_INFO(opline, offset)->call_handler; + const zend_op *prev_opline = opline; + handler = ZEND_OP_TRACE_INFO(opline, offset)->call_handler; #ifdef HAVE_GCC_GLOBAL_REGS handler(); if (UNEXPECTED(opline == zend_jit_halt_op)) { @@ -991,7 +1074,11 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, opline = handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (UNEXPECTED(((uintptr_t)opline & ~ZEND_VM_ENTER_BIT) == 0)) { #endif - stop = ZEND_JIT_TRACE_STOP_RETURN; + if (prev_opline->opcode == ZEND_YIELD || prev_opline->opcode == ZEND_YIELD_FROM) { + stop = ZEND_JIT_TRACE_STOP_INTERPRETER; + } else { + stop = ZEND_JIT_TRACE_STOP_RETURN; + } opline = NULL; halt = ZEND_JIT_TRACE_HALT; break; diff --git a/ext/opcache/opcache.stub.php b/ext/opcache/opcache.stub.php index 526da238219a4..32673bb1dcee8 100644 --- a/ext/opcache/opcache.stub.php +++ b/ext/opcache/opcache.stub.php @@ -23,3 +23,5 @@ function opcache_jit_blacklist(Closure $closure): void {} function opcache_get_configuration(): array|false {} function opcache_is_script_cached(string $filename): bool {} + +function opcache_is_script_cached_in_file_cache(string $filename): bool {} diff --git a/ext/opcache/opcache_arginfo.h b/ext/opcache/opcache_arginfo.h index b4dc1f33a5fd8..7fff6b1eb0da9 100644 --- a/ext/opcache/opcache_arginfo.h +++ b/ext/opcache/opcache_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c416c231c5d1270b7e5961f84cc3ca3e29db4959 */ + * Stub hash: a8de025fa96a78db3a26d53a18bb2b365d094eca */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_opcache_reset, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() @@ -26,6 +26,8 @@ ZEND_END_ARG_INFO() #define arginfo_opcache_is_script_cached arginfo_opcache_compile_file +#define arginfo_opcache_is_script_cached_in_file_cache arginfo_opcache_compile_file + ZEND_FUNCTION(opcache_reset); ZEND_FUNCTION(opcache_get_status); ZEND_FUNCTION(opcache_compile_file); @@ -33,6 +35,7 @@ ZEND_FUNCTION(opcache_invalidate); ZEND_FUNCTION(opcache_jit_blacklist); ZEND_FUNCTION(opcache_get_configuration); ZEND_FUNCTION(opcache_is_script_cached); +ZEND_FUNCTION(opcache_is_script_cached_in_file_cache); static const zend_function_entry ext_functions[] = { ZEND_FE(opcache_reset, arginfo_opcache_reset) @@ -42,5 +45,6 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(opcache_jit_blacklist, arginfo_opcache_jit_blacklist) ZEND_FE(opcache_get_configuration, arginfo_opcache_get_configuration) ZEND_FE(opcache_is_script_cached, arginfo_opcache_is_script_cached) + ZEND_FE(opcache_is_script_cached_in_file_cache, arginfo_opcache_is_script_cached_in_file_cache) ZEND_FE_END }; diff --git a/ext/opcache/shared_alloc_mmap.c b/ext/opcache/shared_alloc_mmap.c index 18c7532478f48..cf5dbb29ebfd9 100644 --- a/ext/opcache/shared_alloc_mmap.c +++ b/ext/opcache/shared_alloc_mmap.c @@ -52,7 +52,7 @@ #endif #if defined(HAVE_JIT) && (defined(__linux__) || defined(__FreeBSD__)) && (defined(__x86_64__) || defined (__aarch64__)) && !defined(__SANITIZE_ADDRESS__) -static void *find_prefered_mmap_base(size_t requested_size) +static void *find_preferred_mmap_base(size_t requested_size) { size_t huge_page_size = 2 * 1024 * 1024; uintptr_t last_free_addr = huge_page_size; @@ -204,7 +204,7 @@ static int create_segments(size_t requested_size, zend_shared_segment ***shared_ void *hint; if (JIT_G(enabled) && JIT_G(buffer_size) && zend_jit_check_support() == SUCCESS) { - hint = find_prefered_mmap_base(requested_size); + hint = find_preferred_mmap_base(requested_size); } else { /* Do not use a hint if JIT is not enabled, as this profits only JIT and * this is potentially unsafe when the only suitable candidate is just diff --git a/ext/opcache/tests/api/opcache_preloading.inc b/ext/opcache/tests/api/opcache_preloading.inc new file mode 100644 index 0000000000000..0466028a3709b --- /dev/null +++ b/ext/opcache/tests/api/opcache_preloading.inc @@ -0,0 +1,3 @@ + diff --git a/ext/opcache/tests/api/opcache_preloading_001.phpt b/ext/opcache/tests/api/opcache_preloading_001.phpt new file mode 100644 index 0000000000000..e30cbbd7d159d --- /dev/null +++ b/ext/opcache/tests/api/opcache_preloading_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +opcache_preloading() api 001 +--EXTENSIONS-- +zend_test +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.preload={PWD}/opcache_preloading.inc +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%sopcache_preloading.inc: 1 +%sopcache_preloading_001.php: 0 diff --git a/ext/opcache/tests/api/opcache_preloading_002.phpt b/ext/opcache/tests/api/opcache_preloading_002.phpt new file mode 100644 index 0000000000000..30bf5a5bc03b1 --- /dev/null +++ b/ext/opcache/tests/api/opcache_preloading_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +opcache_preloading() api 002 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.preload={PWD}/opcache_preloading.inc +opcache.preload_user={ENV:TEST_NON_ROOT_USER} +--EXTENSIONS-- +posix +zend_test +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%sopcache_preloading.inc: 1 +%sopcache_preloading_002.php: 0 diff --git a/ext/opcache/tests/bug71127.phpt b/ext/opcache/tests/bug71127.phpt index a417f0d3120ae..68f6d36895d04 100644 --- a/ext/opcache/tests/bug71127.phpt +++ b/ext/opcache/tests/bug71127.phpt @@ -21,5 +21,5 @@ include($file); @unlink(__DIR__ . "/bug71127.inc"); ?> --EXPECTF-- -Warning: Constant FOO already defined in %sbug71127.inc on line %d +Warning: Constant FOO already defined, this will be an error in PHP 9 in %sbug71127.inc on line %d okey diff --git a/ext/opcache/tests/gh16979_check_file_cache_function.inc b/ext/opcache/tests/gh16979_check_file_cache_function.inc new file mode 100644 index 0000000000000..6e4c482985fba --- /dev/null +++ b/ext/opcache/tests/gh16979_check_file_cache_function.inc @@ -0,0 +1,3 @@ + +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=disable +opcache.file_cache="{PWD}/gh16979_cache" +opcache.file_update_protection=0 +--EXTENSIONS-- +opcache +--FILE-- + +--CLEAN-- +isDir()) { + @rmdir($fileinfo->getRealPath()); + } else { + @unlink($fileinfo->getRealPath()); + } + } + @rmdir($dir); +} +removeDirRecursive(__DIR__ . '/gh16979_cache'); +?> +--EXPECT-- +bool(false) +bool(true) +bool(false) diff --git a/ext/opcache/tests/gh17422/001.phpt b/ext/opcache/tests/gh17422/001.phpt new file mode 100644 index 0000000000000..04a8bc38a9efa --- /dev/null +++ b/ext/opcache/tests/gh17422/001.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) +--FILE-- + +--EXPECT-- +set_error_handler: "continue" targeting switch is equivalent to "break" +OK: warning diff --git a/ext/opcache/tests/gh17422/002.phpt b/ext/opcache/tests/gh17422/002.phpt new file mode 100644 index 0000000000000..6145f71a8e587 --- /dev/null +++ b/ext/opcache/tests/gh17422/002.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Throwing error handler +--FILE-- +getMessage(), PHP_EOL; +} + +warning(); + +?> +--EXPECT-- +Caught: "continue" targeting switch is equivalent to "break" +OK: warning diff --git a/ext/opcache/tests/gh17422/003.phpt b/ext/opcache/tests/gh17422/003.phpt new file mode 100644 index 0000000000000..a1330eb88afab --- /dev/null +++ b/ext/opcache/tests/gh17422/003.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Fatal Error +--FILE-- + +--EXPECTF-- +Fatal error: Cannot redeclare function fatal_error() (previously declared in %s:%d) in %s on line %d diff --git a/ext/opcache/tests/gh17422/004.phpt b/ext/opcache/tests/gh17422/004.phpt new file mode 100644 index 0000000000000..4fa659a763e8d --- /dev/null +++ b/ext/opcache/tests/gh17422/004.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - eval +--FILE-- + +--EXPECTF-- +Fatal error: Cannot redeclare function warning() %s diff --git a/ext/opcache/tests/gh17422/005.phpt b/ext/opcache/tests/gh17422/005.phpt new file mode 100644 index 0000000000000..1b4818d91cc98 --- /dev/null +++ b/ext/opcache/tests/gh17422/005.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - require +--FILE-- + +--EXPECT-- +OK: dummy diff --git a/ext/opcache/tests/gh17422/006.phpt b/ext/opcache/tests/gh17422/006.phpt new file mode 100644 index 0000000000000..3c1303dfa8444 --- /dev/null +++ b/ext/opcache/tests/gh17422/006.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - File cache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_cache="{TMP}" +opcache.file_cache_only=1 +opcache.record_warnings=1 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECT-- +set_error_handler: "continue" targeting switch is equivalent to "break" +OK: warning diff --git a/ext/opcache/tests/gh17422/007.phpt b/ext/opcache/tests/gh17422/007.phpt new file mode 100644 index 0000000000000..59b2306f52d89 --- /dev/null +++ b/ext/opcache/tests/gh17422/007.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Fatal after warning +--FILE-- + +--EXPECTF-- +Warning: "continue" targeting switch is equivalent to "break" in %s on line %d + +Fatal error: Cannot redeclare function warning() (previously declared in %s:%d) in %s on line %d diff --git a/ext/opcache/tests/gh17422/008.phpt b/ext/opcache/tests/gh17422/008.phpt new file mode 100644 index 0000000000000..bcabb071e6502 --- /dev/null +++ b/ext/opcache/tests/gh17422/008.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Early binding warning +--FILE-- + +--EXPECTF-- +set_error_handler: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice diff --git a/ext/opcache/tests/gh17422/009.phpt b/ext/opcache/tests/gh17422/009.phpt new file mode 100644 index 0000000000000..b071ad9478ded --- /dev/null +++ b/ext/opcache/tests/gh17422/009.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Early binding error after warning +--FILE-- + +--EXPECTF-- +Deprecated: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in %s on line %d + +Fatal error: Declaration of C::getTimestamp(C $arg): int must be compatible with DateTime::getTimestamp(): int in %s on line %d diff --git a/ext/opcache/tests/gh17422/010.phpt b/ext/opcache/tests/gh17422/010.phpt new file mode 100644 index 0000000000000..4e94b5e779410 --- /dev/null +++ b/ext/opcache/tests/gh17422/010.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Inheritance warning +--FILE-- + +--EXPECTF-- +set_error_handler: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice diff --git a/ext/opcache/tests/gh17422/011.phpt b/ext/opcache/tests/gh17422/011.phpt new file mode 100644 index 0000000000000..7034e5b2a4612 --- /dev/null +++ b/ext/opcache/tests/gh17422/011.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Inheritance error after warning +--FILE-- + +--EXPECTF-- +Deprecated: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in %s on line %d + +Fatal error: Declaration of C::getTimestamp(C $arg): int must be compatible with DateTime::getTimestamp(): int %s on line %d diff --git a/ext/opcache/tests/gh17422/dummy.inc b/ext/opcache/tests/gh17422/dummy.inc new file mode 100644 index 0000000000000..0bb253556124a --- /dev/null +++ b/ext/opcache/tests/gh17422/dummy.inc @@ -0,0 +1,4 @@ +value = $value['value']; + } + return $item; + }, + null, + CacheItem::class); + return $test($value); +} + +$values = [['value'=>'str'], ['value'=>'str'], ['value'=>42]]; +$n = count($values); + +for ($i = 0; $i < $n; $i++) { + test($values[$i]); +} +?> +OK +--EXPECT-- +OK diff --git a/ext/opcache/tests/jit/copy_tmp_001.phpt b/ext/opcache/tests/jit/copy_tmp_001.phpt index fa92b6ba21ee5..8e3a2a96bd4f3 100644 --- a/ext/opcache/tests/jit/copy_tmp_001.phpt +++ b/ext/opcache/tests/jit/copy_tmp_001.phpt @@ -15,7 +15,10 @@ $a = []; $a[test()] ??= 1; var_dump($a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d array(1) { [""]=> int(1) diff --git a/ext/opcache/tests/jit/fetch_dim_r_002.phpt b/ext/opcache/tests/jit/fetch_dim_r_002.phpt index fb7471d7a292b..324cc688c2220 100644 --- a/ext/opcache/tests/jit/fetch_dim_r_002.phpt +++ b/ext/opcache/tests/jit/fetch_dim_r_002.phpt @@ -30,7 +30,7 @@ $x=2; $y="x"; foo($x.$y); ?> ---EXPECT-- +--EXPECTF-- int(1) int(3) int(2) @@ -38,6 +38,8 @@ int(1) int(3) int(1) int(2) + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d int(4) int(5) int(5) diff --git a/ext/opcache/tests/jit/fetch_list_r_001.phpt b/ext/opcache/tests/jit/fetch_list_r_001.phpt index ec93b305ffafa..f5f0fee4084e5 100644 --- a/ext/opcache/tests/jit/fetch_list_r_001.phpt +++ b/ext/opcache/tests/jit/fetch_list_r_001.phpt @@ -13,5 +13,6 @@ function test() { } test(); ?> ---EXPECT-- +--EXPECTF-- +Warning: Cannot use string as array in %s on line %d NULL diff --git a/ext/opcache/tests/jit/gh18898_1.phpt b/ext/opcache/tests/jit/gh18898_1.phpt new file mode 100644 index 0000000000000..6038f006f5e5c --- /dev/null +++ b/ext/opcache/tests/jit/gh18898_1.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-18898 (SEGV zend_jit_op_array_hot with property hooks and preloading) - jit 1235 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=1235 +opcache.jit_buffer_size=16M +opcache.preload={PWD}/../gh18534_preload.inc +--EXTENSIONS-- +opcache +--SKIPIF-- + +--FILE-- +dummyProperty2); +echo "ok"; +?> +--EXPECT-- +NULL +ok diff --git a/ext/opcache/tests/jit/gh18898_2.phpt b/ext/opcache/tests/jit/gh18898_2.phpt new file mode 100644 index 0000000000000..0ce79b859a979 --- /dev/null +++ b/ext/opcache/tests/jit/gh18898_2.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-18898 (SEGV zend_jit_op_array_hot with property hooks and preloading) - jit 1233 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=1233 +opcache.jit_buffer_size=16M +opcache.preload={PWD}/../gh18534_preload.inc +--EXTENSIONS-- +opcache +--SKIPIF-- + +--FILE-- +dummyProperty2); +echo "ok"; +?> +--EXPECT-- +NULL +ok diff --git a/ext/opcache/tests/jit/gh19486.phpt b/ext/opcache/tests/jit/gh19486.phpt new file mode 100644 index 0000000000000..8a0c610ed200a --- /dev/null +++ b/ext/opcache/tests/jit/gh19486.phpt @@ -0,0 +1,42 @@ +--TEST-- +GH-19486: incorrect opline after deoptimization +--INI-- +opcache.jit_blacklist_root_trace=1 +opcache.jit_blacklist_side_trace=1 +--FILE-- +getLakeArea(0, 0); + +class GameMap +{ + public $lakeID = []; + + public function getLakeArea(int $x, int $y): int + { + $this->floodFill(0, 0, 0); + } + + public function floodFill(int $x, int $y, int $id): void + { + if (($x < 0) or ($x >= 50) or ($y < 0) or ($y >= 50)) { + return; + } + if (isset($this->lakeID[$y][$x]) and ($this->lakeID[$y][$x] == $id)) { + return; + } + $this->lakeID[$y][$x] = $id; + $this->floodFill($x - 1, $y, $id); + $this->floodFill($x + 1, $y, $id); + $this->floodFill($x, $y - 1, $id); + $this->floodFill($x, $y + 1, $id); + } +} + +?> +--EXPECTF-- +Fatal error: Uncaught TypeError: GameMap::getLakeArea(): Return value must be of type int, none returned in %s:%d +Stack trace: +#0 %s(%d): GameMap->getLakeArea(0, 0) +#1 {main} + thrown in %s on line %d diff --git a/ext/opcache/tests/jit/gh19493-001.phpt b/ext/opcache/tests/jit/gh19493-001.phpt new file mode 100644 index 0000000000000..68e5d6e240191 --- /dev/null +++ b/ext/opcache/tests/jit/gh19493-001.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19493 001: Var not stored before YIELD +--FILE-- +getReturn()); + +?> +--EXPECT-- +int(99) diff --git a/ext/opcache/tests/jit/gh19493-002.phpt b/ext/opcache/tests/jit/gh19493-002.phpt new file mode 100644 index 0000000000000..57f2a9826730f --- /dev/null +++ b/ext/opcache/tests/jit/gh19493-002.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19493 002: Var not stored before YIELD_FROM +--FILE-- +getReturn()); + +?> +--EXPECT-- +int(99) diff --git a/ext/opcache/tests/jit/gh19669-001.phpt b/ext/opcache/tests/jit/gh19669-001.phpt new file mode 100644 index 0000000000000..7d63643bb0157 --- /dev/null +++ b/ext/opcache/tests/jit/gh19669-001.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19669: assertion failure zend_jit_trace_type_to_info_ex +--CREDITS-- +YuanchengJiang +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(-3) diff --git a/ext/opcache/tests/jit/gh19669-002.phpt b/ext/opcache/tests/jit/gh19669-002.phpt new file mode 100644 index 0000000000000..373356bcd0612 --- /dev/null +++ b/ext/opcache/tests/jit/gh19669-002.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19669 002: assertion failure zend_jit_trace_type_to_info_ex +--CREDITS-- +YuanchengJiang +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(-10) diff --git a/ext/opcache/tests/jit/inc_022.phpt b/ext/opcache/tests/jit/inc_022.phpt index 9b13f51dc23da..2c091d98d4086 100644 --- a/ext/opcache/tests/jit/inc_022.phpt +++ b/ext/opcache/tests/jit/inc_022.phpt @@ -22,7 +22,8 @@ var_dump(inc(1.1)); var_dump(dec("5")); var_dump(dec(1.1)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(3) "abd" int(6) float(2.1) diff --git a/ext/opcache/tests/jit/inc_023.phpt b/ext/opcache/tests/jit/inc_023.phpt index ef832c096ae7d..516e5a45aa7d6 100644 --- a/ext/opcache/tests/jit/inc_023.phpt +++ b/ext/opcache/tests/jit/inc_023.phpt @@ -19,7 +19,11 @@ var_dump(++$test->prop); var_dump(--$test->prop); ?> --EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d + Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(1) "c" Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d diff --git a/ext/opcache/tests/jit/inc_024.phpt b/ext/opcache/tests/jit/inc_024.phpt index e125f9b084df6..5e6e2bbfe75f2 100644 --- a/ext/opcache/tests/jit/inc_024.phpt +++ b/ext/opcache/tests/jit/inc_024.phpt @@ -23,52 +23,52 @@ function test($b) { test("0"); ?> --EXPECTF-- -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d -Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d string(5) "-INF0" string(260) "0-2-12-112-1112-11112-111112-1111112-11111112-111111112-1111111112-11111111112-111111111112-1111111111112-11111111111112-111111111111112-1111111111111112-11111111111111112-111111111111111112-1111111111111111112-1.1111111111111E+20-1.1111111111111E+191-ING-INF1" diff --git a/ext/opcache/tests/opcache_enable_noop_001.phpt b/ext/opcache/tests/opcache_enable_noop_001.phpt new file mode 100644 index 0000000000000..0e7f5bbc98793 --- /dev/null +++ b/ext/opcache/tests/opcache_enable_noop_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +Dynamically setting opcache.enable does not warn when noop +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +Should not warn: +Disabling: +Should warn: + +Warning: Zend OPcache can't be temporarily enabled (it may be only disabled until the end of request) in %s on line %d diff --git a/ext/opcache/tests/opcache_enable_noop_002.phpt b/ext/opcache/tests/opcache_enable_noop_002.phpt new file mode 100644 index 0000000000000..994f2d22f4e45 --- /dev/null +++ b/ext/opcache/tests/opcache_enable_noop_002.phpt @@ -0,0 +1,18 @@ +--TEST-- +Dynamically setting opcache.enable warns when not a noop +--INI-- +opcache.enable=0 +opcache.enable_cli=1 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +Should warn, since the INI was initialized to 0: + +Warning: Zend OPcache can't be temporarily enabled (it may be only disabled until the end of request) in %s on line %d diff --git a/ext/opcache/tests/opt/block_pass_003.phpt b/ext/opcache/tests/opt/block_pass_003.phpt index 25d32e1e4d70e..c8690add9b839 100644 --- a/ext/opcache/tests/opt/block_pass_003.phpt +++ b/ext/opcache/tests/opt/block_pass_003.phpt @@ -1,5 +1,5 @@ --TEST-- -Block Pass 003: Inorrect constant substitution in FETCH_LIST_R +Block Pass 003: Incorrect constant substitution in FETCH_LIST_R --INI-- opcache.enable=1 opcache.enable_cli=1 @@ -16,5 +16,44 @@ function test() { test(); ?> DONE ---EXPECT-- +--EXPECTF-- +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d + +Warning: Cannot use int as array in %s on line %d DONE diff --git a/ext/opcache/tests/opt/gh11245_2.phpt b/ext/opcache/tests/opt/gh11245_2.phpt index f42da12c52743..ade810c453b13 100644 --- a/ext/opcache/tests/opt/gh11245_2.phpt +++ b/ext/opcache/tests/opt/gh11245_2.phpt @@ -34,3 +34,5 @@ $_main: 0006 RETURN int(1) LIVE RANGES: 1: 0001 - 0005 (tmp/var) + +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %s on line %d diff --git a/ext/opcache/tests/opt/gh18107_1.phpt b/ext/opcache/tests/opt/gh18107_1.phpt index c99fa7efa40d3..fea270a4d5a08 100644 --- a/ext/opcache/tests/opt/gh18107_1.phpt +++ b/ext/opcache/tests/opt/gh18107_1.phpt @@ -41,6 +41,7 @@ $_main: 0011 FAST_RET T5 EXCEPTION TABLE: 0006, -, 0007, 0011 + Fatal error: Uncaught Exception: Should happen in %s:%d Stack trace: #0 {main} diff --git a/ext/opcache/tests/opt/gh18107_2.phpt b/ext/opcache/tests/opt/gh18107_2.phpt index 573bcd5ae4a6f..aaf58b4f820de 100644 --- a/ext/opcache/tests/opt/gh18107_2.phpt +++ b/ext/opcache/tests/opt/gh18107_2.phpt @@ -48,6 +48,7 @@ $_main: 0015 RETURN int(1) EXCEPTION TABLE: 0006, 0006, 0010, 0014 + Fatal error: Uncaught Exception: Should happen in %s:%d Stack trace: #0 {main} diff --git a/ext/opcache/tests/opt/gh19792.phpt b/ext/opcache/tests/opt/gh19792.phpt new file mode 100644 index 0000000000000..edd805ca57a19 --- /dev/null +++ b/ext/opcache/tests/opt/gh19792.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19792 (SCCP causes UAF for return value if both warning and exception are triggered) +--EXTENSIONS-- +opcache +zend_test +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECTF-- +Warning: a warning in %s on line %d +an exception diff --git a/ext/opcache/tests/opt/sccp_038.phpt b/ext/opcache/tests/opt/sccp_038.phpt index 165206056c6e5..b2d7e79c5fe05 100644 --- a/ext/opcache/tests/opt/sccp_038.phpt +++ b/ext/opcache/tests/opt/sccp_038.phpt @@ -15,5 +15,5 @@ foo(); ?> DONE --EXPECTF-- -Deprecated: Increment on non-alphanumeric string is deprecated in %ssccp_038.php on line 5 +Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in %ssccp_038.php on line 5 DONE diff --git a/ext/opcache/tests/preload_dynamic_def_removal.inc b/ext/opcache/tests/preload_dynamic_def_removal.inc index 27ec69120eac5..2a6a44ef509a2 100644 --- a/ext/opcache/tests/preload_dynamic_def_removal.inc +++ b/ext/opcache/tests/preload_dynamic_def_removal.inc @@ -5,6 +5,15 @@ class Test { echo "dynamic\n"; } } + + public int $hook { + get { + function dynamic_in_hook() { + echo "dynamic in hook\n"; + } + return 1; + } + } } function func() { @@ -16,3 +25,4 @@ function func() { $test = new Test; $test->method(); func(); +$test->hook; diff --git a/ext/opcache/tests/preload_dynamic_def_removal.phpt b/ext/opcache/tests/preload_dynamic_def_removal.phpt index d4f2bb070ccd5..acc26873e1867 100644 --- a/ext/opcache/tests/preload_dynamic_def_removal.phpt +++ b/ext/opcache/tests/preload_dynamic_def_removal.phpt @@ -15,7 +15,9 @@ if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows --EXPECT-- dynamic dynamic2 +dynamic in hook diff --git a/ext/opcache/tests/revalidate_path_01.phpt b/ext/opcache/tests/revalidate_path_01.phpt index ff87e73b55441..c8cd1ea493a63 100644 --- a/ext/opcache/tests/revalidate_path_01.phpt +++ b/ext/opcache/tests/revalidate_path_01.phpt @@ -30,7 +30,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { @rmdir($link); $ln = str_replace('/', '\\', $link); $d1 = realpath($dir1); - `mklink /j $ln $d1`; + shell_exec("mklink /j $ln $d1"); } else { @unlink($link); @symlink($dir1, $link); @@ -45,7 +45,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { @rmdir($link); $ln = str_replace('/', '\\', $link); $d2 = realpath($dir2); - `mklink /j $ln $d2`; + shell_exec("mklink /j $ln $d2"); } else { @unlink($link); @symlink($dir2, $link); diff --git a/ext/opcache/tests/zzz_basic_logging.phpt b/ext/opcache/tests/zzz_basic_logging.phpt index a53c6a8db9de1..88290f6a169d9 100644 --- a/ext/opcache/tests/zzz_basic_logging.phpt +++ b/ext/opcache/tests/zzz_basic_logging.phpt @@ -13,12 +13,14 @@ opcache.log_verbosity_level=4 opcache.huge_code_pages=0 opcache.preload= opcache.interned_strings_buffer=8 +opcache.blacklist_filename= --EXTENSIONS-- opcache --SKIPIF-- --FILE-- | - +----------------------------------------------------------------------+ */ -#ifndef PACK_H -#define PACK_H - -PHP_MINIT_FUNCTION(pack); +#include "zend_accelerator_api.h" +#include "ZendAccelerator.h" -#endif /* PACK_H */ +ZEND_API bool opcache_preloading(void) +{ + return ZCG(preloading); +} diff --git a/ext/standard/php_smart_string_public.h b/ext/opcache/zend_accelerator_api.h similarity index 74% rename from ext/standard/php_smart_string_public.h rename to ext/opcache/zend_accelerator_api.h index 264723e28e1b2..4ea42f29d174a 100644 --- a/ext/standard/php_smart_string_public.h +++ b/ext/opcache/zend_accelerator_api.h @@ -1,4 +1,6 @@ /* + +----------------------------------------------------------------------+ + | Zend OPcache | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ @@ -10,10 +12,18 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Sascha Schumann | - | Xinchen Hui | - +----------------------------------------------------------------------+ - */ +*/ + +#ifndef ZEND_ACCELERATOR_API_H +#define ZEND_ACCELERATOR_API_H + +#include "Zend/zend_portability.h" + +BEGIN_EXTERN_C() + +/* Returns true during preloading */ +ZEND_API bool opcache_preloading(void); + +END_EXTERN_C() -/* Header moved to Zend. This file is retained for BC. */ -#include "zend_smart_string_public.h" +#endif /* ZEND_ACCELERATOR_API_H */ diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 203a41d93b40a..6f668af9b714d 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -25,8 +25,11 @@ #include "ZendAccelerator.h" #include "zend_API.h" #include "zend_closures.h" +#include "zend_extensions.h" +#include "zend_modules.h" #include "zend_shared_alloc.h" #include "zend_accelerator_blacklist.h" +#include "zend_file_cache.h" #include "php_ini.h" #include "SAPI.h" #include "zend_virtual_cwd.h" @@ -76,6 +79,15 @@ static int validate_api_restriction(void) static ZEND_INI_MH(OnUpdateMemoryConsumption) { + if (accel_startup_ok) { + if (strcmp(sapi_module.name, "fpm-fcgi") == 0) { + zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption cannot be changed when OPcache is already set up. Are you using php_admin_value[opcache.memory_consumption] in an individual pool's configuration?\n"); + } else { + zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption cannot be changed when OPcache is already set up.\n"); + } + return FAILURE; + } + zend_long *p = (zend_long *) ZEND_INI_GET_ADDR(); zend_long memsize = atoi(ZSTR_VAL(new_value)); /* sanity check we must use at least 8 MB */ @@ -147,10 +159,23 @@ static ZEND_INI_MH(OnEnable) stage == ZEND_INI_STAGE_DEACTIVATE) { return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } else { - /* It may be only temporary disabled */ + /* It may be only temporarily disabled */ bool *p = (bool *) ZEND_INI_GET_ADDR(); if (zend_ini_parse_bool(new_value)) { - zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporary enabled (it may be only disabled till the end of request)"); + if (*p) { + /* Do not warn if OPcache is enabled, as the update would be a noop anyways. */ + return SUCCESS; + } + + if (stage == ZEND_INI_STAGE_ACTIVATE) { + if (strcmp(sapi_module.name, "fpm-fcgi") == 0) { + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporarily enabled. Are you using php_admin_value[opcache.enable]=1 in an individual pool's configuration?"); + } else { + zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporarily enabled (it may be only disabled until the end of request)"); + } + } else { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporarily enabled (it may be only disabled until the end of request)"); + } return FAILURE; } else { *p = 0; @@ -323,7 +348,7 @@ ZEND_INI_BEGIN() STD_PHP_INI_ENTRY("opcache.jit_max_root_traces" , "1024", PHP_INI_SYSTEM, OnUpdateLong, max_root_traces, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_max_side_traces" , "128", PHP_INI_SYSTEM, OnUpdateLong, max_side_traces, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_max_exit_counters" , "8192", PHP_INI_SYSTEM, OnUpdateLong, max_exit_counters, zend_jit_globals, jit_globals) - /* Defautl value should be a prime number, to reduce the chances of loop iterations being a factor of opcache.jit_hot_loop */ + /* Default value should be a prime number, to reduce the chances of loop iterations being a factor of opcache.jit_hot_loop */ STD_PHP_INI_ENTRY("opcache.jit_hot_loop" , "61", PHP_INI_SYSTEM, OnUpdateCounter, hot_loop, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_hot_func" , "127", PHP_INI_SYSTEM, OnUpdateCounter, hot_func, zend_jit_globals, jit_globals) STD_PHP_INI_ENTRY("opcache.jit_hot_return" , "8", PHP_INI_SYSTEM, OnUpdateCounter, hot_return, zend_jit_globals, jit_globals) @@ -364,6 +389,23 @@ static int filename_is_in_cache(zend_string *filename) return 0; } +static int filename_is_in_file_cache(zend_string *filename) +{ + zend_string *realpath = zend_resolve_path(filename); + if (!realpath) { + return 0; + } + + zend_file_handle handle; + zend_stream_init_filename_ex(&handle, filename); + handle.opened_path = realpath; + + zend_persistent_script *result = zend_file_cache_script_load_ex(&handle, true); + zend_destroy_file_handle(&handle); + + return result != NULL; +} + static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS) { if (ZEND_NUM_ARGS() == 1) { @@ -405,13 +447,19 @@ static ZEND_NAMED_FUNCTION(accel_is_readable) static ZEND_MINIT_FUNCTION(zend_accelerator) { - (void)type; /* keep the compiler happy */ - - REGISTER_INI_ENTRIES(); + start_accel_extension(); return SUCCESS; } +void zend_accel_register_ini_entries(void) +{ + zend_module_entry *module = zend_hash_str_find_ptr_lc(&module_registry, + ACCELERATOR_PRODUCT_NAME, strlen(ACCELERATOR_PRODUCT_NAME)); + + zend_register_ini_entries_ex(ini_entries, module->module_number, module->type); +} + void zend_accel_override_file_functions(void) { zend_function *old_function; @@ -442,6 +490,7 @@ static ZEND_MSHUTDOWN_FUNCTION(zend_accelerator) UNREGISTER_INI_ENTRIES(); accel_shutdown(); + return SUCCESS; } @@ -554,7 +603,7 @@ void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS) DISPLAY_INI_ENTRIES(); } -static zend_module_entry accel_module_entry = { +zend_module_entry opcache_module_entry = { STANDARD_MODULE_HEADER, ACCELERATOR_PRODUCT_NAME, ext_functions, @@ -569,11 +618,6 @@ static zend_module_entry accel_module_entry = { STANDARD_MODULE_PROPERTIES_EX }; -int start_accel_module(void) -{ - return zend_startup_module(&accel_module_entry); -} - /* {{{ Get the scripts which are accelerated by ZendAccelerator */ static int accelerator_get_scripts(zval *return_value) { @@ -581,8 +625,6 @@ static int accelerator_get_scripts(zval *return_value) zval persistent_script_report; zend_accel_hash_entry *cache_entry; struct tm *ta; - struct timeval exec_time; - struct timeval fetch_time; if (!ZCG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) { return 0; @@ -612,8 +654,6 @@ static int accelerator_get_scripts(zval *return_value) if (ZCG(accel_directives).validate_timestamps) { add_assoc_long(&persistent_script_report, "timestamp", (zend_long)script->timestamp); } - timerclear(&exec_time); - timerclear(&fetch_time); add_assoc_long(&persistent_script_report, "revalidate", (zend_long)script->dynamic_members.revalidate); @@ -999,3 +1039,27 @@ ZEND_FUNCTION(opcache_is_script_cached) RETURN_BOOL(filename_is_in_cache(script_name)); } + +/* {{{ Return true if the script is cached in OPCache file cache, false if it is not cached or if OPCache is not running. */ +ZEND_FUNCTION(opcache_is_script_cached_in_file_cache) +{ + zend_string *script_name; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(script_name) + ZEND_PARSE_PARAMETERS_END(); + + if (!validate_api_restriction()) { + RETURN_FALSE; + } + + if (!(ZCG(accelerator_enabled) || ZCG(accel_directives).file_cache_only)) { + RETURN_FALSE; + } + + if (!ZCG(accel_directives).file_cache) { + RETURN_FALSE; + } + + RETURN_BOOL(filename_is_in_file_cache(script_name)); +} diff --git a/ext/opcache/zend_accelerator_module.h b/ext/opcache/zend_accelerator_module.h index 656336eeba762..6eff0624bbbf1 100644 --- a/ext/opcache/zend_accelerator_module.h +++ b/ext/opcache/zend_accelerator_module.h @@ -22,7 +22,12 @@ #ifndef ZEND_ACCELERATOR_MODULE_H #define ZEND_ACCELERATOR_MODULE_H -int start_accel_module(void); +#include "Zend/zend_modules.h" + +#define phpext_opcache_ptr &opcache_module_entry +extern zend_module_entry opcache_module_entry; + +void zend_accel_register_ini_entries(void); void zend_accel_override_file_functions(void); diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index fee90e42b574f..4ec285be84348 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -461,6 +461,7 @@ static void zend_file_cache_serialize_attribute(zval *zv, SERIALIZE_STR(attr->name); SERIALIZE_STR(attr->lcname); + SERIALIZE_STR(attr->validation_error); for (i = 0; i < attr->argc; i++) { SERIALIZE_STR(attr->args[i].name); @@ -1352,6 +1353,7 @@ static void zend_file_cache_unserialize_attribute(zval *zv, zend_persistent_scri UNSERIALIZE_STR(attr->name); UNSERIALIZE_STR(attr->lcname); + UNSERIALIZE_STR(attr->validation_error); for (i = 0; i < attr->argc; i++) { UNSERIALIZE_STR(attr->args[i].name); @@ -1871,7 +1873,14 @@ static void zend_file_cache_unserialize(zend_persistent_script *script, zend_file_cache_unserialize_early_bindings(script, buf); } +static zend_persistent_script file_cache_validate_success_script; + zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle) +{ + return zend_file_cache_script_load_ex(file_handle, false); +} + +zend_persistent_script *zend_file_cache_script_load_ex(zend_file_handle *file_handle, bool validate_only) { zend_string *full_path = file_handle->opened_path; int fd; @@ -1948,6 +1957,16 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl return NULL; } + /* return here if validating */ + if (validate_only) { + if (zend_file_cache_flock(fd, LOCK_UN) != 0) { + zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename); + } + close(fd); + efree(filename); + return &file_cache_validate_success_script; + } + checkpoint = zend_arena_checkpoint(CG(arena)); #if defined(__AVX__) || defined(__SSE2__) /* Align to 64-byte boundary */ diff --git a/ext/opcache/zend_file_cache.h b/ext/opcache/zend_file_cache.h index 8f067f5f37abb..452f6b2c4c243 100644 --- a/ext/opcache/zend_file_cache.h +++ b/ext/opcache/zend_file_cache.h @@ -21,6 +21,7 @@ int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm); zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle); +zend_persistent_script *zend_file_cache_script_load_ex(zend_file_handle *file_handle, bool validate_only); void zend_file_cache_invalidate(zend_string *full_path); #endif /* ZEND_FILE_CACHE_H */ diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 202cd73c90422..38e58d5a16632 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -311,6 +311,9 @@ static HashTable *zend_persist_attributes(HashTable *attributes) zend_accel_store_interned_string(copy->name); zend_accel_store_interned_string(copy->lcname); + if (copy->validation_error) { + zend_accel_store_interned_string(copy->validation_error); + } for (i = 0; i < copy->argc; i++) { if (copy->args[i].name) { @@ -1283,6 +1286,41 @@ void zend_update_parent_ce(zend_class_entry *ce) } } +#ifdef HAVE_JIT +static void zend_accel_persist_jit_op_array(zend_op_array *op_array, zend_class_entry *ce) +{ + if (op_array->type == ZEND_USER_FUNCTION) { + if (op_array->scope == ce + && !(op_array->fn_flags & ZEND_ACC_ABSTRACT) + && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { + zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL); + for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) { + zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL); + } + } + } +} + +static void zend_accel_persist_link_func_info(zend_op_array *op_array, zend_class_entry *ce) +{ + if (op_array->type == ZEND_USER_FUNCTION + && !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) { + if ((op_array->scope != ce + || (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) + && (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC + || JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST + || JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS + || JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) { + void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes); + + if (jit_extension) { + ZEND_SET_FUNC_INFO(op_array, jit_extension); + } + } + } +} +#endif + static void zend_accel_persist_class_table(HashTable *class_table) { Bucket *p; @@ -1309,44 +1347,48 @@ static void zend_accel_persist_class_table(HashTable *class_table) if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS && !ZCG(current_persistent_script)->corrupted) { zend_op_array *op_array; + zend_property_info *prop; ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) { if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) { ce = Z_PTR(p->val); ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { - if (op_array->type == ZEND_USER_FUNCTION) { - if (op_array->scope == ce - && !(op_array->fn_flags & ZEND_ACC_ABSTRACT) - && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) { - zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL); - for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) { - zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL); + zend_accel_persist_jit_op_array(op_array, ce); + } ZEND_HASH_FOREACH_END(); + + if (ce->num_hooked_props > 0) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { + if (prop->hooks) { + for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { + if (prop->hooks[i]) { + op_array = &prop->hooks[i]->op_array; + zend_accel_persist_jit_op_array(op_array, ce); + } } } - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } } } ZEND_HASH_FOREACH_END(); ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) { if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) { ce = Z_PTR(p->val); ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) { - if (op_array->type == ZEND_USER_FUNCTION - && !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) { - if ((op_array->scope != ce - || (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) - && (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC - || JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST - || JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS - || JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) { - void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes); - - if (jit_extension) { - ZEND_SET_FUNC_INFO(op_array, jit_extension); + zend_accel_persist_link_func_info(op_array, ce); + } ZEND_HASH_FOREACH_END(); + + if (ce->num_hooked_props > 0) { + ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) { + if (prop->hooks) { + for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) { + if (prop->hooks[i]) { + op_array = &prop->hooks[i]->op_array; + zend_accel_persist_link_func_info(op_array, ce); + } } } - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } } } ZEND_HASH_FOREACH_END(); } @@ -1355,11 +1397,11 @@ static void zend_accel_persist_class_table(HashTable *class_table) zend_error_info **zend_persist_warnings(uint32_t num_warnings, zend_error_info **warnings) { if (warnings) { - warnings = zend_shared_memdup_free(warnings, num_warnings * sizeof(zend_error_info *)); + warnings = zend_shared_memdup(warnings, num_warnings * sizeof(zend_error_info *)); for (uint32_t i = 0; i < num_warnings; i++) { - warnings[i] = zend_shared_memdup_free(warnings[i], sizeof(zend_error_info)); zend_accel_store_string(warnings[i]->filename); zend_accel_store_string(warnings[i]->message); + warnings[i] = zend_shared_memdup(warnings[i], sizeof(zend_error_info)); } } return warnings; diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 639d7d5446705..106a69f5dd383 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -181,6 +181,9 @@ static void zend_persist_attributes_calc(HashTable *attributes) ADD_SIZE(ZEND_ATTRIBUTE_SIZE(attr->argc)); ADD_INTERNED_STRING(attr->name); ADD_INTERNED_STRING(attr->lcname); + if (attr->validation_error != NULL) { + ADD_INTERNED_STRING(attr->validation_error); + } for (i = 0; i < attr->argc; i++) { if (attr->args[i].name) { diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 37dbe59f3d55c..80ef36b8749d9 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -229,6 +229,9 @@ int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size) if (!g_shared_alloc_handler) { /* try memory handlers in order */ + if (handler_table->name == NULL) { + return NO_SHM_BACKEND; + } for (he = handler_table; he->name; he++) { res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in); if (res) { diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h index 41cba0bb35199..108349b13f816 100644 --- a/ext/opcache/zend_shared_alloc.h +++ b/ext/opcache/zend_shared_alloc.h @@ -72,6 +72,7 @@ #define SUCCESSFULLY_REATTACHED 4 #define ALLOC_FAIL_MAPPING 8 #define ALLOC_FALLBACK 9 +#define NO_SHM_BACKEND 10 typedef struct _zend_shared_segment { size_t size; diff --git a/ext/openssl/config0.m4 b/ext/openssl/config0.m4 index 774213336b6ee..15d1feb96eeab 100644 --- a/ext/openssl/config0.m4 +++ b/ext/openssl/config0.m4 @@ -49,9 +49,6 @@ if test "$PHP_OPENSSL" != "no"; then the default provider.])]) AS_VAR_IF([PHP_OPENSSL_ARGON2], [no],, [ - AS_VAR_IF([PHP_THREAD_SAFETY], [yes], - [AC_MSG_ERROR([Not supported in ZTS mode for now])]) - PHP_CHECK_LIBRARY([crypto], [OSSL_set_max_threads], [AC_DEFINE([HAVE_OPENSSL_ARGON2], [1], [Define to 1 to enable OpenSSL argon2 password hashing.])], diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 4d1567f56d8c2..65ae0372253c0 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -351,12 +351,39 @@ int php_openssl_get_ssl_stream_data_index(void) return ssl_stream_data_index; } -/* {{{ INI Settings */ +static PHP_INI_MH(OnUpdateLibCtx) +{ +#if PHP_OPENSSL_API_VERSION >= 0x30000 + if (zend_string_equals_literal(new_value, "default")) { +#if defined(ZTS) && defined(HAVE_OPENSSL_ARGON2) + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + int err_type = stage == ZEND_INI_STAGE_RUNTIME ? E_WARNING : E_ERROR; + php_error_docref(NULL, err_type, "OpenSSL libctx \"default\" cannot be used in this configuration"); + } + return FAILURE; +#else + OPENSSL_G(ctx).libctx = OPENSSL_G(ctx).default_libctx; +#endif + } else if (zend_string_equals_literal(new_value, "custom")) { + OPENSSL_G(ctx).libctx = OPENSSL_G(ctx).custom_libctx; + } else { + /* Do not output error when restoring ini options. */ + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + int err_type = stage == ZEND_INI_STAGE_RUNTIME ? E_WARNING : E_ERROR; + php_error_docref(NULL, err_type, "OpenSSL libctx \"%s\" cannot be found", ZSTR_VAL(new_value)); + } + return FAILURE; + } +#endif + + return SUCCESS; +} + PHP_INI_BEGIN() PHP_INI_ENTRY("openssl.cafile", NULL, PHP_INI_PERDIR, NULL) PHP_INI_ENTRY("openssl.capath", NULL, PHP_INI_PERDIR, NULL) + PHP_INI_ENTRY("openssl.libctx", "custom", PHP_INI_PERDIR, OnUpdateLibCtx) PHP_INI_END() -/* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(openssl) @@ -438,9 +465,7 @@ PHP_GINIT_FUNCTION(openssl) #endif openssl_globals->errors = NULL; openssl_globals->errors_mark = NULL; -#if PHP_OPENSSL_API_VERSION >= 0x30000 - php_openssl_backend_init_libctx(&openssl_globals->libctx, &openssl_globals->propq); -#endif + php_openssl_backend_init_libctx(&openssl_globals->ctx); } /* }}} */ @@ -453,9 +478,7 @@ PHP_GSHUTDOWN_FUNCTION(openssl) if (openssl_globals->errors_mark) { pefree(openssl_globals->errors_mark, 1); } -#if PHP_OPENSSL_API_VERSION >= 0x30000 - php_openssl_backend_destroy_libctx(openssl_globals->libctx, openssl_globals->propq); -#endif + php_openssl_backend_destroy_libctx(&openssl_globals->ctx); } /* }}} */ @@ -2333,6 +2356,14 @@ PHP_FUNCTION(openssl_pkey_derive) RETURN_THROWS(); } + if (ZEND_NUM_ARGS() == 3) { + php_error_docref(NULL, E_DEPRECATED, + "the $key_length parameter is deprecated as it is either ignored or truncates the key"); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } + } + if (key_len < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); @@ -2395,9 +2426,9 @@ PHP_FUNCTION(openssl_pbkdf2) } if (method_len) { - digest = EVP_get_digestbyname(method); + digest = php_openssl_get_evp_md_by_name(method); } else { - digest = EVP_sha1(); + digest = php_openssl_get_evp_md_by_name("SHA1"); } if (!digest) { @@ -2718,7 +2749,7 @@ PHP_FUNCTION(openssl_pkcs7_read) goto clean_exit; } - p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); + p7 = php_openssl_pem_read_bio_pkcs7(bio_in); if (p7 == NULL) { php_openssl_store_errors(); goto clean_exit; @@ -3040,19 +3071,19 @@ PHP_FUNCTION(openssl_cms_verify) switch (encoding) { case ENCODING_PEM: - cms = PEM_read_bio_CMS(sigbio, NULL, 0, NULL); - datain = in; - break; - case ENCODING_DER: - cms = d2i_CMS_bio(sigbio, NULL); - datain = in; - break; - case ENCODING_SMIME: - cms = SMIME_read_CMS(sigbio, &datain); - break; - default: - php_error_docref(NULL, E_WARNING, "Unknown encoding"); - goto clean_exit; + cms = php_openssl_pem_read_bio_cms(sigbio); + datain = in; + break; + case ENCODING_DER: + cms = php_openssl_d2i_bio_cms(sigbio); + datain = in; + break; + case ENCODING_SMIME: + cms = php_openssl_smime_read_cms(sigbio, &datain); + break; + default: + php_error_docref(NULL, E_WARNING, "Unknown encoding"); + goto clean_exit; } if (cms == NULL) { php_openssl_store_errors(); @@ -3170,6 +3201,7 @@ PHP_FUNCTION(openssl_cms_encrypt) X509 * cert; const EVP_CIPHER *cipher = NULL; zend_long cipherid = PHP_OPENSSL_CIPHER_DEFAULT; + zend_string *cipher_str = NULL; zend_string * strindex; char * infilename = NULL; size_t infilename_len; @@ -3179,11 +3211,16 @@ PHP_FUNCTION(openssl_cms_encrypt) RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ppza!|lll", &infilename, &infilename_len, - &outfilename, &outfilename_len, &zrecipcerts, &zheaders, &flags, &encoding, &cipherid) == FAILURE) { - RETURN_THROWS(); - } - + ZEND_PARSE_PARAMETERS_START(4, 7) + Z_PARAM_PATH(infilename, infilename_len) + Z_PARAM_PATH(outfilename, outfilename_len) + Z_PARAM_ZVAL(zrecipcerts) + Z_PARAM_ARRAY_OR_NULL(zheaders) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(flags) + Z_PARAM_LONG(encoding) + Z_PARAM_STR_OR_LONG(cipher_str, cipherid) + ZEND_PARSE_PARAMETERS_END(); infile = php_openssl_bio_new_file( infilename, infilename_len, 1, PHP_OPENSSL_BIO_MODE_R(flags)); @@ -3242,7 +3279,11 @@ PHP_FUNCTION(openssl_cms_encrypt) } /* sanity check the cipher */ - cipher = php_openssl_get_evp_cipher_from_algo(cipherid); + if (cipher_str) { + cipher = php_openssl_get_evp_cipher_by_name(ZSTR_VAL(cipher_str)); + } else { + cipher = php_openssl_get_evp_cipher_from_algo(cipherid); + } if (cipher == NULL) { /* shouldn't happen */ php_error_docref(NULL, E_WARNING, "Failed to get cipher"); @@ -3367,7 +3408,7 @@ PHP_FUNCTION(openssl_cms_read) goto clean_exit; } - cms = PEM_read_bio_CMS(bio_in, NULL, NULL, NULL); + cms = php_openssl_pem_read_bio_cms(bio_in); if (cms == NULL) { php_openssl_store_errors(); goto clean_exit; @@ -3672,13 +3713,13 @@ PHP_FUNCTION(openssl_cms_decrypt) switch (encoding) { case ENCODING_DER: - cms = d2i_CMS_bio(in, NULL); + cms = php_openssl_d2i_bio_cms(in); break; case ENCODING_PEM: - cms = PEM_read_bio_CMS(in, NULL, 0, NULL); + cms = php_openssl_pem_read_bio_cms(in); break; case ENCODING_SMIME: - cms = SMIME_read_CMS(in, &datain); + cms = php_openssl_smime_read_cms(in, &datain); break; default: zend_argument_value_error(5, "must be an OPENSSL_ENCODING_* constant"); @@ -3710,6 +3751,29 @@ PHP_FUNCTION(openssl_cms_decrypt) /* }}} */ +/* Helper to set RSA padding and digest for OAEP */ +static int php_openssl_set_rsa_padding_and_digest(EVP_PKEY_CTX *ctx, zend_long padding, const char *digest_algo, const EVP_MD **pmd) +{ + if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0) { + return 0; + } + + if (digest_algo != NULL) { + const EVP_MD *md = php_openssl_get_evp_md_by_name(digest_algo); + if (md == NULL) { + php_error_docref(NULL, E_WARNING, "Unknown digest algorithm: %s", digest_algo); + return 0; + } + *pmd = md; + if (padding == RSA_PKCS1_OAEP_PADDING) { + if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { + return 0; + } + } + } + + return 1; +} /* {{{ Encrypts data with private key */ PHP_FUNCTION(openssl_private_encrypt) @@ -3765,10 +3829,12 @@ PHP_FUNCTION(openssl_private_decrypt) { zval *key, *crypted; zend_long padding = RSA_PKCS1_PADDING; - char * data; - size_t data_len; + char *data; + char *digest_algo = NULL; + size_t data_len, digest_algo_len = 0; + const EVP_MD *md = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|lp!", &data, &data_len, &crypted, &key, &padding, &digest_algo, &digest_algo_len) == FAILURE) { RETURN_THROWS(); } @@ -3783,7 +3849,7 @@ PHP_FUNCTION(openssl_private_decrypt) size_t out_len = 0; EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!ctx || EVP_PKEY_decrypt_init(ctx) <= 0 || - EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + !php_openssl_set_rsa_padding_and_digest(ctx, padding, digest_algo, &md) || EVP_PKEY_decrypt(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) { php_openssl_store_errors(); RETVAL_FALSE; @@ -3805,6 +3871,7 @@ PHP_FUNCTION(openssl_private_decrypt) RETVAL_TRUE; cleanup: + php_openssl_release_evp_md(md); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); } @@ -3816,9 +3883,11 @@ PHP_FUNCTION(openssl_public_encrypt) zval *key, *crypted; zend_long padding = RSA_PKCS1_PADDING; char * data; - size_t data_len; + char *digest_algo = NULL; + size_t data_len, digest_algo_len = 0; + const EVP_MD *md = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|lp!", &data, &data_len, &crypted, &key, &padding, &digest_algo, &digest_algo_len) == FAILURE) { RETURN_THROWS(); } @@ -3833,7 +3902,7 @@ PHP_FUNCTION(openssl_public_encrypt) size_t out_len = 0; EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!ctx || EVP_PKEY_encrypt_init(ctx) <= 0 || - EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + !php_openssl_set_rsa_padding_and_digest(ctx, padding, digest_algo, &md) || EVP_PKEY_encrypt(ctx, NULL, &out_len, (unsigned char *) data, data_len) <= 0) { php_openssl_store_errors(); RETVAL_FALSE; @@ -3854,6 +3923,7 @@ PHP_FUNCTION(openssl_public_encrypt) RETVAL_TRUE; cleanup: + php_openssl_release_evp_md(md); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); } @@ -3864,7 +3934,7 @@ PHP_FUNCTION(openssl_public_decrypt) { zval *key, *crypted; zend_long padding = RSA_PKCS1_PADDING; - char * data; + char *data; size_t data_len; if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { @@ -3937,6 +4007,30 @@ PHP_FUNCTION(openssl_error_string) } /* }}} */ +static zend_result php_openssl_setup_rsa_padding(EVP_PKEY_CTX *pctx, EVP_PKEY *pkey, zend_long padding) +{ + int key_type = EVP_PKEY_type(EVP_PKEY_id(pkey)); + + if (padding != 0) { // 0 = default/unspecified + if (key_type != EVP_PKEY_RSA) { + php_error_docref(NULL, E_WARNING, "Padding parameter is only supported for RSA keys"); + return FAILURE; + } + + if (padding == RSA_PKCS1_PSS_PADDING) { + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0) { + php_openssl_store_errors(); + return FAILURE; + } + } else if (padding != RSA_PKCS1_PADDING) { + php_error_docref(NULL, E_WARNING, "Unknown padding type"); + return FAILURE; + } + } + + return SUCCESS; +} + /* {{{ Signs data */ PHP_FUNCTION(openssl_sign) { @@ -3949,14 +4043,17 @@ PHP_FUNCTION(openssl_sign) zend_string *method_str = NULL; zend_long method_long = OPENSSL_ALGO_SHA1; const EVP_MD *mdtype; + zend_long padding = 0; + EVP_PKEY_CTX *pctx; bool can_default_digest = ZEND_THREEWAY_COMPARE(PHP_OPENSSL_API_VERSION, 0x30000) >= 0; - ZEND_PARSE_PARAMETERS_START(3, 4) + ZEND_PARSE_PARAMETERS_START(3, 5) Z_PARAM_STRING(data, data_len) Z_PARAM_ZVAL(signature) Z_PARAM_ZVAL(key) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_LONG(method_str, method_long) + Z_PARAM_LONG(padding) ZEND_PARSE_PARAMETERS_END(); pkey = php_openssl_pkey_from_zval(key, 0, "", 0, 3); @@ -3981,7 +4078,8 @@ PHP_FUNCTION(openssl_sign) md_ctx = EVP_MD_CTX_create(); size_t siglen; if (md_ctx != NULL && - EVP_DigestSignInit(md_ctx, NULL, mdtype, NULL, pkey) && + EVP_DigestSignInit(md_ctx, &pctx, mdtype, NULL, pkey) && + php_openssl_setup_rsa_padding(pctx, pkey, padding) == SUCCESS && EVP_DigestSign(md_ctx, NULL, &siglen, (unsigned char*)data, data_len) && (sigbuf = zend_string_alloc(siglen, 0)) != NULL && EVP_DigestSign(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, (unsigned char*)data, data_len)) { @@ -4014,14 +4112,17 @@ PHP_FUNCTION(openssl_verify) size_t signature_len; zend_string *method_str = NULL; zend_long method_long = OPENSSL_ALGO_SHA1; + zend_long padding = 0; + EVP_PKEY_CTX *pctx; bool can_default_digest = ZEND_THREEWAY_COMPARE(PHP_OPENSSL_API_VERSION, 0x30000) >= 0; - ZEND_PARSE_PARAMETERS_START(3, 4) + ZEND_PARSE_PARAMETERS_START(3, 5) Z_PARAM_STRING(data, data_len) Z_PARAM_STRING(signature, signature_len) Z_PARAM_ZVAL(key) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_LONG(method_str, method_long) + Z_PARAM_LONG(padding) ZEND_PARSE_PARAMETERS_END(); PHP_OPENSSL_CHECK_SIZE_T_TO_UINT(signature_len, signature, 2); @@ -4046,11 +4147,25 @@ PHP_FUNCTION(openssl_verify) } md_ctx = EVP_MD_CTX_create(); - if (md_ctx == NULL || - !EVP_DigestVerifyInit(md_ctx, NULL, mdtype, NULL, pkey) || - (err = EVP_DigestVerify(md_ctx, (unsigned char *)signature, signature_len, (unsigned char*)data, data_len)) < 0) { + if (md_ctx == NULL) { + php_openssl_store_errors(); + err = -1; + goto cleanup; + } + + if (!EVP_DigestVerifyInit(md_ctx, &pctx, mdtype, NULL, pkey) || + php_openssl_setup_rsa_padding(pctx, pkey, padding) == FAILURE) { php_openssl_store_errors(); + err = -1; + goto cleanup; } + + err = EVP_DigestVerify(md_ctx, (unsigned char *)signature, signature_len, (unsigned char*)data, data_len); + if (err < 0) { + php_openssl_store_errors(); + } + +cleanup: EVP_MD_CTX_destroy(md_ctx); php_openssl_release_evp_md(mdtype); EVP_PKEY_free(pkey); @@ -4087,7 +4202,7 @@ PHP_FUNCTION(openssl_seal) RETURN_THROWS(); } - cipher = EVP_get_cipherbyname(method); + cipher = php_openssl_get_evp_cipher_by_name(method); if (!cipher) { php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm"); RETURN_FALSE; @@ -4216,7 +4331,7 @@ PHP_FUNCTION(openssl_open) RETURN_FALSE; } - cipher = EVP_get_cipherbyname(method); + cipher = php_openssl_get_evp_cipher_by_name(method); if (!cipher) { php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm"); RETURN_FALSE; diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index 1fe3a9fc168eb..94902a4acf0da 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -166,6 +166,26 @@ * @cvalue PKCS7_NOOLDMIMETYPE */ const PKCS7_NOOLDMIMETYPE = UNKNOWN; +/** + * @var int + * @cvalue PKCS7_NOSMIMECAP + */ +const PKCS7_NOSMIMECAP = UNKNOWN; +/** + * @var int + * @cvalue PKCS7_CRLFEOL + */ +const PKCS7_CRLFEOL = UNKNOWN; +/** + * @var int + * @cvalue PKCS7_NOCRL + */ +const PKCS7_NOCRL = UNKNOWN; +/** + * @var int + * @cvalue PKCS7_NO_DUAL_CONTENT + */ +const PKCS7_NO_DUAL_CONTENT = UNKNOWN; /** * @var int @@ -236,6 +256,11 @@ * @cvalue RSA_PKCS1_OAEP_PADDING */ const OPENSSL_PKCS1_OAEP_PADDING = UNKNOWN; +/** + * @var int + * @cvalue RSA_PKCS1_PSS_PADDING + */ +const OPENSSL_PKCS1_PSS_PADDING = UNKNOWN; /* Informational stream wrapper constants */ @@ -363,7 +388,6 @@ const OPENSSL_DONT_ZERO_PAD_KEY = UNKNOWN; #ifndef OPENSSL_NO_TLSEXT -/** @var int */ const OPENSSL_TLSEXT_SERVER_NAME = 1; #endif @@ -549,7 +573,7 @@ function openssl_pkcs7_read(string $data, &$certificates): bool {} function openssl_cms_verify(string $input_filename, int $flags = 0, ?string $certificates = null, array $ca_info = [], ?string $untrusted_certificates_filename = null, ?string $content = null, ?string $pk7 = null, ?string $sigfile = null, int $encoding = OPENSSL_ENCODING_SMIME): bool {} /** @param OpenSSLCertificate|array|string $certificate */ -function openssl_cms_encrypt(string $input_filename, string $output_filename, $certificate, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, int $cipher_algo = OPENSSL_CIPHER_AES_128_CBC): bool {} +function openssl_cms_encrypt(string $input_filename, string $output_filename, $certificate, ?array $headers, int $flags = 0, int $encoding = OPENSSL_ENCODING_SMIME, string|int $cipher_algo = OPENSSL_CIPHER_AES_128_CBC): bool {} /** * @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key @@ -575,13 +599,13 @@ function openssl_private_encrypt(#[\SensitiveParameter] string $data, &$encrypte * @param string $decrypted_data * @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key */ -function openssl_private_decrypt(string $data, #[\SensitiveParameter] &$decrypted_data, #[\SensitiveParameter] $private_key, int $padding = OPENSSL_PKCS1_PADDING): bool {} +function openssl_private_decrypt(string $data, #[\SensitiveParameter] &$decrypted_data, #[\SensitiveParameter] $private_key, int $padding = OPENSSL_PKCS1_PADDING, ?string $digest_algo = null): bool {} /** * @param string $encrypted_data * @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key */ -function openssl_public_encrypt(#[\SensitiveParameter] string $data, &$encrypted_data, $public_key, int $padding = OPENSSL_PKCS1_PADDING): bool {} +function openssl_public_encrypt(#[\SensitiveParameter] string $data, &$encrypted_data, $public_key, int $padding = OPENSSL_PKCS1_PADDING, ?string $digest_algo = null): bool {} /** * @param string $decrypted_data @@ -595,10 +619,10 @@ function openssl_error_string(): string|false {} * @param string $signature * @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key */ -function openssl_sign(string $data, &$signature, #[\SensitiveParameter] $private_key, string|int $algorithm = OPENSSL_ALGO_SHA1): bool {} +function openssl_sign(string $data, &$signature, #[\SensitiveParameter] $private_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0): bool {} /** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key */ -function openssl_verify(string $data, string $signature, $public_key, string|int $algorithm = OPENSSL_ALGO_SHA1): int|false {} +function openssl_verify(string $data, string $signature, $public_key, string|int $algorithm = OPENSSL_ALGO_SHA1, int $padding = 0): int|false {} /** * @param string $sealed_data diff --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index fb53dcae903e7..796582c185bb6 100644 --- a/ext/openssl/openssl_arginfo.h +++ b/ext/openssl/openssl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a42bd7dec0a5e011983ce08b5e31cd8718247501 */ + * Stub hash: 8233a8abc8ab7145d905d0fa51478edfe1e55a06 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_x509_export_to_file, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_TYPE_MASK(0, certificate, OpenSSLCertificate, MAY_BE_STRING, NULL) @@ -219,7 +219,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_cms_encrypt, 0, 4, _IS_B ZEND_ARG_TYPE_INFO(0, headers, IS_ARRAY, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, encoding, IS_LONG, 0, "OPENSSL_ENCODING_SMIME") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, cipher_algo, IS_LONG, 0, "OPENSSL_CIPHER_AES_128_CBC") + ZEND_ARG_TYPE_MASK(0, cipher_algo, MAY_BE_STRING|MAY_BE_LONG, "OPENSSL_CIPHER_AES_128_CBC") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_cms_sign, 0, 5, _IS_BOOL, 0) @@ -258,6 +258,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_private_decrypt, 0, 3, _ ZEND_ARG_INFO(1, decrypted_data) ZEND_ARG_INFO(0, private_key) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "OPENSSL_PKCS1_PADDING") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, digest_algo, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_public_encrypt, 0, 3, _IS_BOOL, 0) @@ -265,6 +266,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_public_encrypt, 0, 3, _I ZEND_ARG_INFO(1, encrypted_data) ZEND_ARG_INFO(0, public_key) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "OPENSSL_PKCS1_PADDING") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, digest_algo, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_public_decrypt, 0, 3, _IS_BOOL, 0) @@ -282,6 +284,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_sign, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(1, signature) ZEND_ARG_INFO(0, private_key) ZEND_ARG_TYPE_MASK(0, algorithm, MAY_BE_STRING|MAY_BE_LONG, "OPENSSL_ALGO_SHA1") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_verify, 0, 3, MAY_BE_LONG|MAY_BE_FALSE) @@ -289,6 +292,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_verify, 0, 3, MAY_BE_LON ZEND_ARG_TYPE_INFO(0, signature, IS_STRING, 0) ZEND_ARG_INFO(0, public_key) ZEND_ARG_TYPE_MASK(0, algorithm, MAY_BE_STRING|MAY_BE_LONG, "OPENSSL_ALGO_SHA1") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, padding, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_seal, 0, 5, MAY_BE_LONG|MAY_BE_FALSE) @@ -582,6 +586,10 @@ static void register_openssl_symbols(int module_number) REGISTER_LONG_CONSTANT("PKCS7_BINARY", PKCS7_BINARY, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PKCS7_NOSIGS", PKCS7_NOSIGS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PKCS7_NOOLDMIMETYPE", PKCS7_NOOLDMIMETYPE, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PKCS7_NOSMIMECAP", PKCS7_NOSMIMECAP, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PKCS7_CRLFEOL", PKCS7_CRLFEOL, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PKCS7_NOCRL", PKCS7_NOCRL, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PKCS7_NO_DUAL_CONTENT", PKCS7_NO_DUAL_CONTENT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_CMS_DETACHED", CMS_DETACHED, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_CMS_TEXT", CMS_TEXT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_CMS_NOINTERN", CMS_NOINTERN, CONST_PERSISTENT); @@ -597,6 +605,7 @@ static void register_openssl_symbols(int module_number) #endif REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_PSS_PADDING", RSA_PKCS1_PSS_PADDING, CONST_PERSISTENT); REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_PERSISTENT); #if !defined(OPENSSL_NO_RC2) REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_40", PHP_OPENSSL_CIPHER_RC2_40, CONST_PERSISTENT); @@ -640,15 +649,10 @@ static void register_openssl_symbols(int module_number) zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_x509_check_private_key", sizeof("openssl_x509_check_private_key") - 1), 1, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_attribute *attribute_Deprecated_func_openssl_x509_free_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_x509_free", sizeof("openssl_x509_free") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_openssl_x509_free_0_arg0; - zend_string *attribute_Deprecated_func_openssl_x509_free_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_openssl_x509_free_0_arg0, attribute_Deprecated_func_openssl_x509_free_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_openssl_x509_free_0->args[0].value, &attribute_Deprecated_func_openssl_x509_free_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_openssl_x509_free_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_openssl_x509_free_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_openssl_x509_free_0_arg1; zend_string *attribute_Deprecated_func_openssl_x509_free_0_arg1_str = zend_string_init("as OpenSSLCertificate objects are freed automatically", strlen("as OpenSSLCertificate objects are freed automatically"), 1); - ZVAL_STR(&attribute_Deprecated_func_openssl_x509_free_0_arg1, attribute_Deprecated_func_openssl_x509_free_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_openssl_x509_free_0->args[1].value, &attribute_Deprecated_func_openssl_x509_free_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_openssl_x509_free_0->args[1].value, attribute_Deprecated_func_openssl_x509_free_0_arg1_str); attribute_Deprecated_func_openssl_x509_free_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_pkcs12_export_to_file", sizeof("openssl_pkcs12_export_to_file") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); @@ -674,27 +678,16 @@ static void register_openssl_symbols(int module_number) zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_pkey_export", sizeof("openssl_pkey_export") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_attribute *attribute_Deprecated_func_openssl_pkey_free_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_pkey_free", sizeof("openssl_pkey_free") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_openssl_pkey_free_0_arg0; - zend_string *attribute_Deprecated_func_openssl_pkey_free_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_openssl_pkey_free_0_arg0, attribute_Deprecated_func_openssl_pkey_free_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_openssl_pkey_free_0->args[0].value, &attribute_Deprecated_func_openssl_pkey_free_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_openssl_pkey_free_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_openssl_pkey_free_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_openssl_pkey_free_0_arg1; zend_string *attribute_Deprecated_func_openssl_pkey_free_0_arg1_str = zend_string_init("as OpenSSLAsymmetricKey objects are freed automatically", strlen("as OpenSSLAsymmetricKey objects are freed automatically"), 1); - ZVAL_STR(&attribute_Deprecated_func_openssl_pkey_free_0_arg1, attribute_Deprecated_func_openssl_pkey_free_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_openssl_pkey_free_0->args[1].value, &attribute_Deprecated_func_openssl_pkey_free_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_openssl_pkey_free_0->args[1].value, attribute_Deprecated_func_openssl_pkey_free_0_arg1_str); attribute_Deprecated_func_openssl_pkey_free_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_openssl_free_key_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_free_key", sizeof("openssl_free_key") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_openssl_free_key_0_arg0; - zend_string *attribute_Deprecated_func_openssl_free_key_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_openssl_free_key_0_arg0, attribute_Deprecated_func_openssl_free_key_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_openssl_free_key_0->args[0].value, &attribute_Deprecated_func_openssl_free_key_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_openssl_free_key_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_openssl_free_key_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_openssl_free_key_0_arg1; - zend_string *attribute_Deprecated_func_openssl_free_key_0_arg1_str = zend_string_init("as OpenSSLAsymmetricKey objects are freed automatically", strlen("as OpenSSLAsymmetricKey objects are freed automatically"), 1); - ZVAL_STR(&attribute_Deprecated_func_openssl_free_key_0_arg1, attribute_Deprecated_func_openssl_free_key_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_openssl_free_key_0->args[1].value, &attribute_Deprecated_func_openssl_free_key_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_openssl_free_key_0->args[1].value, attribute_Deprecated_func_openssl_pkey_free_0_arg1_str); attribute_Deprecated_func_openssl_free_key_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_pkey_get_private", sizeof("openssl_pkey_get_private") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c index 42b70c72a9cd0..5a8919d3eacf2 100644 --- a/ext/openssl/openssl_backend_common.c +++ b/ext/openssl/openssl_backend_common.c @@ -297,12 +297,12 @@ int php_openssl_parse_config(struct php_x509_request * req, zval * optional_args SET_OPTIONAL_STRING_ARG("config", req->config_filename, default_ssl_conf_filename); SET_OPTIONAL_STRING_ARG("config_section_name", req->section_name, "req"); - req->global_config = NCONF_new(NULL); + req->global_config = php_openssl_nconf_new(); if (!NCONF_load(req->global_config, default_ssl_conf_filename, NULL)) { php_openssl_store_errors(); } - req->req_config = NCONF_new(NULL); + req->req_config = php_openssl_nconf_new(); if (!NCONF_load(req->req_config, req->config_filename, NULL)) { return FAILURE; } @@ -440,7 +440,7 @@ zend_result php_openssl_load_rand_file(const char * file, int *egdsocket, int *s return SUCCESS; #endif } - if (file == NULL || !RAND_load_file(file, -1)) { + if (file == NULL || RAND_load_file(file, -1) < 0) { if (RAND_status() == 0) { php_openssl_store_errors(); php_error_docref(NULL, E_WARNING, "Unable to load random state; not enough random data!"); @@ -465,7 +465,7 @@ zend_result php_openssl_write_rand_file(const char * file, int egdsocket, int se if (file == NULL) { file = RAND_file_name(buffer, sizeof(buffer)); } - if (file == NULL || !RAND_write_file(file)) { + if (file == NULL || RAND_write_file(file) < 0) { php_openssl_store_errors(); php_error_docref(NULL, E_WARNING, "Unable to write random state"); return FAILURE; @@ -541,18 +541,14 @@ X509 *php_openssl_x509_from_str( php_openssl_store_errors(); return NULL; } - cert = PEM_read_bio_X509(in, NULL, NULL, NULL); + cert = php_openssl_pem_read_bio_x509(in); } else { in = BIO_new_mem_buf(ZSTR_VAL(cert_str), (int) ZSTR_LEN(cert_str)); if (in == NULL) { php_openssl_store_errors(); return NULL; } -#ifdef TYPEDEF_D2I_OF - cert = (X509 *) PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL); -#else - cert = (X509 *) PEM_ASN1_read_bio((char *(*)())d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL); -#endif + cert = php_openssl_pem_read_asn1_bio_x509(in); } if (!BIO_free(in)) { @@ -612,7 +608,7 @@ zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, bool r unsigned int n; zend_string *ret; - if (!(mdtype = EVP_get_digestbyname(method))) { + if (!(mdtype = php_openssl_get_evp_md_by_name(method))) { php_error_docref(NULL, E_WARNING, "Unknown digest algorithm"); return NULL; } else if (!X509_digest(peer, mdtype, md, &n)) { @@ -1127,7 +1123,7 @@ X509_REQ *php_openssl_csr_from_str(zend_string *csr_str, uint32_t arg_num) return NULL; } - csr = PEM_read_bio_X509_REQ(in, NULL,NULL,NULL); + csr = php_openssl_pem_read_bio_x509_req(in); if (csr == NULL) { php_openssl_store_errors(); } @@ -1158,7 +1154,7 @@ EVP_PKEY *php_openssl_extract_public_key(EVP_PKEY *priv_key) return NULL; } - EVP_PKEY *pub_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + EVP_PKEY *pub_key = php_openssl_pem_read_bio_public_key(bio); BIO_free(bio); return pub_key; } @@ -1290,7 +1286,7 @@ EVP_PKEY *php_openssl_pkey_from_zval( zend_string_release_ex(val_str, false); TMP_CLEAN; } - key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL); + key = php_openssl_pem_read_bio_public_key(in); BIO_free(in); } } else { @@ -1308,12 +1304,12 @@ EVP_PKEY *php_openssl_pkey_from_zval( TMP_CLEAN; } if (passphrase == NULL) { - key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); + key = php_openssl_pem_read_bio_private_key(in, NULL, NULL); } else { struct php_openssl_pem_password password; password.key = passphrase; password.len = passphrase_len; - key = PEM_read_bio_PrivateKey(in, NULL, php_openssl_pem_password_cb, &password); + key = php_openssl_pem_read_bio_private_key(in, php_openssl_pem_password_cb, &password); } BIO_free(in); } @@ -1344,13 +1340,20 @@ EVP_PKEY *php_openssl_pkey_from_zval( return key; } -zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t key_size) -{ - EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_pkey(key); +zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t requested_key_size) { + size_t key_size = requested_key_size; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL); if (!ctx) { return NULL; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L + /* OpenSSL 1.1 does not respect key_size for DH, so force size discovery so it can be compared later. */ + if (EVP_PKEY_base_id(key) == EVP_PKEY_DH && key_size != 0) { + key_size = 0; + } +#endif + if (EVP_PKEY_derive_init(ctx) <= 0 || EVP_PKEY_derive_set_peer(ctx, peer_key) <= 0 || (key_size == 0 && EVP_PKEY_derive(ctx, NULL, &key_size) <= 0)) { @@ -1359,6 +1362,14 @@ zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t k return NULL; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L + /* Now compare the computed size for DH to mirror OpenSSL 3.0+ behavior. */ + if (EVP_PKEY_base_id(key) == EVP_PKEY_DH && requested_key_size > 0 && requested_key_size < key_size) { + EVP_PKEY_CTX_free(ctx); + return NULL; + } +#endif + zend_string *result = zend_string_alloc(key_size, 0); if (EVP_PKEY_derive(ctx, (unsigned char *)ZSTR_VAL(result), &key_size) <= 0) { php_openssl_store_errors(); @@ -1671,7 +1682,7 @@ zend_result php_openssl_validate_iv(const char **piv, size_t *piv_len, size_t iv char *iv_new; if (mode->is_aead) { - if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_ivlen_flag, *piv_len, NULL) != 1) { + if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_ivlen_flag, *piv_len, NULL) <= 0) { php_error_docref(NULL, E_WARNING, "Setting of IV length for AEAD mode failed"); return FAILURE; } @@ -1742,7 +1753,7 @@ zend_result php_openssl_cipher_init(const EVP_CIPHER *cipher_type, return FAILURE; } if (mode->set_tag_length_always || (enc && mode->set_tag_length_when_encrypting)) { - if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, NULL)) { + if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, NULL) <= 0) { php_error_docref(NULL, E_WARNING, "Setting tag length for AEAD cipher failed"); return FAILURE; } @@ -1750,7 +1761,7 @@ zend_result php_openssl_cipher_init(const EVP_CIPHER *cipher_type, if (!enc && tag && tag_len > 0) { if (!mode->is_aead) { php_error_docref(NULL, E_WARNING, "The tag cannot be used because the cipher algorithm does not support AEAD"); - } else if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, (unsigned char *) tag)) { + } else if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, (unsigned char *) tag) <= 0) { php_error_docref(NULL, E_WARNING, "Setting tag for AEAD cipher decryption failed"); return FAILURE; } @@ -1886,7 +1897,7 @@ PHP_OPENSSL_API zend_string* php_openssl_encrypt( if (mode.is_aead && tag) { zend_string *tag_str = zend_string_alloc(tag_len, 0); - if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode.aead_get_tag_flag, tag_len, ZSTR_VAL(tag_str)) == 1) { + if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode.aead_get_tag_flag, tag_len, ZSTR_VAL(tag_str)) > 0) { ZSTR_VAL(tag_str)[tag_len] = '\0'; ZSTR_LEN(tag_str) = tag_len; ZEND_TRY_ASSIGN_REF_NEW_STR(tag, tag_str); diff --git a/ext/openssl/openssl_backend_v1.c b/ext/openssl/openssl_backend_v1.c index 8b9ede38437d6..c15fff2f795ed 100644 --- a/ext/openssl/openssl_backend_v1.c +++ b/ext/openssl/openssl_backend_v1.c @@ -44,6 +44,16 @@ void php_openssl_backend_shutdown(void) #endif } +void php_openssl_backend_init_libctx(struct php_openssl_libctx *ctx) +{ + // Do nothing as there is no libctx +} + +void php_openssl_backend_destroy_libctx(struct php_openssl_libctx *ctx) +{ + // Do nothing as there is no libctx +} + EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id) { return EVP_PKEY_CTX_new_id(id, NULL); @@ -677,4 +687,54 @@ void php_openssl_get_cipher_methods(zval *return_value, bool aliases) return_value); } +CONF *php_openssl_nconf_new(void) +{ + return NCONF_new(NULL); +} + +X509 *php_openssl_pem_read_asn1_bio_x509(BIO *in) +{ + return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL); +} + +X509 *php_openssl_pem_read_bio_x509(BIO *in) +{ + return PEM_read_bio_X509(in, NULL, NULL, NULL); +} + +X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in) +{ + return PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); +} + +EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in) +{ + return PEM_read_bio_PUBKEY(in, NULL, NULL, NULL); +} + +EVP_PKEY *php_openssl_pem_read_bio_private_key(BIO *in, pem_password_cb *cb, void *u) +{ + return PEM_read_bio_PrivateKey(in, NULL, cb, u); +} + +PKCS7 *php_openssl_pem_read_bio_pkcs7(BIO *in) +{ + return PEM_read_bio_PKCS7(in, NULL, NULL, NULL); +} + +CMS_ContentInfo *php_openssl_pem_read_bio_cms(BIO *in) +{ + return PEM_read_bio_CMS(in, NULL, NULL, NULL); +} + +CMS_ContentInfo *php_openssl_d2i_bio_cms(BIO *in) +{ + return d2i_CMS_bio(in, NULL); +} + +CMS_ContentInfo *php_openssl_smime_read_cms(BIO *bio, BIO **bcont) +{ + return SMIME_read_CMS(bio, bcont); +} + #endif diff --git a/ext/openssl/openssl_backend_v3.c b/ext/openssl/openssl_backend_v3.c index e3c80cf659ba1..16f145b2c5f5e 100644 --- a/ext/openssl/openssl_backend_v3.c +++ b/ext/openssl/openssl_backend_v3.c @@ -29,32 +29,47 @@ void php_openssl_backend_shutdown(void) (void) 0; } -void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq) +#define PHP_OPENSSL_DEFAULT_CONF_MFLAGS \ + (CONF_MFLAGS_DEFAULT_SECTION | CONF_MFLAGS_IGNORE_MISSING_FILE | CONF_MFLAGS_IGNORE_RETURN_CODES) + +void php_openssl_backend_init_libctx(struct php_openssl_libctx *ctx) { - /* The return value is not checked because we cannot reasonable fail in GINIT so using NULL - * (default context) is probably better. */ - *plibctx = OSSL_LIB_CTX_new(); - *ppropq = NULL; + ctx->default_libctx = OSSL_LIB_CTX_get0_global_default(); + ctx->custom_libctx = OSSL_LIB_CTX_new(); + if (ctx->custom_libctx != NULL) { + /* This is not being checked because there is not much that can be done. */ + CONF_modules_load_file_ex(ctx->custom_libctx, NULL, NULL, + PHP_OPENSSL_DEFAULT_CONF_MFLAGS); +#ifdef LOAD_OPENSSL_LEGACY_PROVIDER + OSSL_PROVIDER_load(ctx->custom_libctx, "legacy"); + OSSL_PROVIDER_load(ctx->custom_libctx, "default"); +#endif + ctx->libctx = ctx->custom_libctx; + } else { + /* If creation fails, just fallback to default */ + ctx->libctx = ctx->default_libctx; + } + ctx->propq = NULL; } -void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq) +void php_openssl_backend_destroy_libctx(struct php_openssl_libctx *ctx) { - if (libctx != NULL) { - OSSL_LIB_CTX_free(libctx); + if (ctx->custom_libctx != NULL) { + OSSL_LIB_CTX_free(ctx->custom_libctx); } - if (propq != NULL) { - free(propq); + if (ctx->propq != NULL) { + free(ctx->propq); } } EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id) { - return EVP_PKEY_CTX_new_from_name(OPENSSL_G(libctx), name, OPENSSL_G(propq)); + return EVP_PKEY_CTX_new_from_name(PHP_OPENSSL_LIBCTX, name, PHP_OPENSSL_PROPQ); } EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey) { - return EVP_PKEY_CTX_new_from_pkey(OPENSSL_G(libctx), pkey, OPENSSL_G(propq)); + return EVP_PKEY_CTX_new_from_pkey(PHP_OPENSSL_LIBCTX, pkey, PHP_OPENSSL_PROPQ); } EVP_PKEY *php_openssl_pkey_init_rsa(zval *data) @@ -299,7 +314,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { goto cleanup; } - if (!(group = EC_GROUP_new_by_curve_name_ex(OPENSSL_G(libctx), OPENSSL_G(propq), nid))) { + if (!(group = EC_GROUP_new_by_curve_name_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ, nid))) { goto cleanup; } @@ -698,7 +713,13 @@ zend_string *php_openssl_dh_compute_key(EVP_PKEY *pkey, char *pub_str, size_t pu const EVP_MD *php_openssl_get_evp_md_by_name(const char *name) { - return EVP_MD_fetch(OPENSSL_G(libctx), name, OPENSSL_G(propq)); + const EVP_MD *dp = (const EVP_MD *) OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH); + + if (dp != NULL) { + return dp; + } + + return EVP_MD_fetch(PHP_OPENSSL_LIBCTX, name, PHP_OPENSSL_PROPQ); } static const char *php_openssl_digest_names[] = { @@ -754,7 +775,13 @@ static const char *php_openssl_cipher_names[] = { const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *name) { - return EVP_CIPHER_fetch(OPENSSL_G(libctx), name, OPENSSL_G(propq)); + const EVP_CIPHER *cp = (const EVP_CIPHER *) OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH); + + if (cp != NULL) { + return cp; + } + + return EVP_CIPHER_fetch(PHP_OPENSSL_LIBCTX, name, PHP_OPENSSL_PROPQ); } const EVP_CIPHER *php_openssl_get_evp_cipher_from_algo(zend_long algo) @@ -805,10 +832,137 @@ static int php_openssl_compare_func(Bucket *a, Bucket *b) void php_openssl_get_cipher_methods(zval *return_value, bool aliases) { array_init(return_value); - EVP_CIPHER_do_all_provided(OPENSSL_G(libctx), + EVP_CIPHER_do_all_provided(PHP_OPENSSL_LIBCTX, aliases ? php_openssl_add_cipher_or_alias : php_openssl_add_cipher, return_value); zend_hash_sort(Z_ARRVAL_P(return_value), php_openssl_compare_func, 1); } +CONF *php_openssl_nconf_new(void) +{ + return NCONF_new_ex(PHP_OPENSSL_LIBCTX, NULL); +} + +X509 *php_openssl_pem_read_asn1_bio_x509(BIO *in) +{ + X509 *x = X509_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); + + if (x == NULL) { + return NULL; + } + + if (PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, in, (void **) &x, NULL, NULL) == NULL) { + X509_free(x); + return NULL; + } + + return x; +} + +X509 *php_openssl_pem_read_bio_x509(BIO *in) +{ + X509 *x = X509_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); + + if (x == NULL) { + return NULL; + } + + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { + X509_free(x); + return NULL; + } + + return x; +} + +X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in) +{ + X509_REQ *xr = X509_REQ_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); + + if (xr == NULL) { + return NULL; + } + + if (PEM_read_bio_X509_REQ(in, &xr, NULL, NULL) == NULL) { + X509_REQ_free(xr); + return NULL; + } + + return xr; +} + +EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in) +{ + return PEM_read_bio_PUBKEY_ex(in, NULL, NULL, NULL, PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); +} + +EVP_PKEY *php_openssl_pem_read_bio_private_key(BIO *in, pem_password_cb *cb, void *u) +{ + return PEM_read_bio_PrivateKey_ex(in, NULL, cb, u, PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); +} + +PKCS7 *php_openssl_pem_read_bio_pkcs7(BIO *in) +{ + PKCS7 *p = PKCS7_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); + + if (p == NULL) { + return NULL; + } + + if (PEM_read_bio_PKCS7(in, &p, NULL, NULL) == NULL) { + PKCS7_free(p); + return NULL; + } + + return p; +} + +CMS_ContentInfo *php_openssl_pem_read_bio_cms(BIO *in) +{ + CMS_ContentInfo *ci = CMS_ContentInfo_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); + + if (ci == NULL) { + return NULL; + } + + if (PEM_read_bio_CMS(in, &ci, NULL, NULL) == NULL) { + CMS_ContentInfo_free(ci); + return NULL; + } + + return ci; +} + +CMS_ContentInfo *php_openssl_d2i_bio_cms(BIO *in) +{ + CMS_ContentInfo *ci = CMS_ContentInfo_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); + + if (ci == NULL) { + return NULL; + } + + if (d2i_CMS_bio(in, &ci) == NULL) { + CMS_ContentInfo_free(ci); + return NULL; + } + + return ci; +} + +CMS_ContentInfo *php_openssl_smime_read_cms(BIO *bio, BIO **bcont) +{ + CMS_ContentInfo *ci = CMS_ContentInfo_new_ex(PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ); + + if (ci == NULL) { + return NULL; + } + + if (SMIME_read_CMS_ex(bio, 0, bcont, &ci) == NULL) { + CMS_ContentInfo_free(ci); + return NULL; + } + + return ci; +} + #endif diff --git a/ext/openssl/openssl_pwhash.c b/ext/openssl/openssl_pwhash.c index 5fe5bb5cf1bba..dc125e3b516db 100644 --- a/ext/openssl/openssl_pwhash.c +++ b/ext/openssl/openssl_pwhash.c @@ -22,7 +22,7 @@ #include "ext/standard/php_password.h" #include "php_openssl.h" -#if defined(HAVE_OPENSSL_ARGON2) +#ifdef HAVE_OPENSSL_ARGON2 #include "Zend/zend_attributes.h" #include "openssl_pwhash_arginfo.h" #include @@ -46,6 +46,8 @@ #define PHP_OPENSSL_HASH_SIZE 32 #define PHP_OPENSSL_DIGEST_SIZE 128 +ZEND_EXTERN_MODULE_GLOBALS(openssl) + static inline zend_result get_options(zend_array *options, uint32_t *memlimit, uint32_t *iterlimit, uint32_t *threads) { zval *opt; @@ -98,8 +100,8 @@ static bool php_openssl_argon2_compute_hash( uint32_t oldthreads; bool ret = false; - oldthreads = OSSL_get_max_threads(NULL); - if (OSSL_set_max_threads(NULL, threads) != 1) { + oldthreads = OSSL_get_max_threads(PHP_OPENSSL_LIBCTX); + if (OSSL_set_max_threads(PHP_OPENSSL_LIBCTX, threads) != 1) { goto fail; } p = params; @@ -111,7 +113,7 @@ static bool php_openssl_argon2_compute_hash( *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, (void *)pass, pass_len); *p++ = OSSL_PARAM_construct_end(); - if ((kdf = EVP_KDF_fetch(NULL, algo, NULL)) == NULL) { + if ((kdf = EVP_KDF_fetch(PHP_OPENSSL_LIBCTX, algo, PHP_OPENSSL_PROPQ)) == NULL) { goto fail; } if ((kctx = EVP_KDF_CTX_new(kdf)) == NULL) { @@ -127,7 +129,7 @@ static bool php_openssl_argon2_compute_hash( fail: EVP_KDF_free(kdf); EVP_KDF_CTX_free(kctx); - OSSL_set_max_threads(NULL, oldthreads); + OSSL_set_max_threads(PHP_OPENSSL_LIBCTX, oldthreads); return ret; } @@ -385,4 +387,5 @@ PHP_MINIT_FUNCTION(openssl_pwhash) return SUCCESS; } + #endif /* HAVE_OPENSSL_ARGON2 */ diff --git a/ext/openssl/openssl_pwhash.stub.php b/ext/openssl/openssl_pwhash.stub.php index c6e3a363c5220..49e2663557dcd 100644 --- a/ext/openssl/openssl_pwhash.stub.php +++ b/ext/openssl/openssl_pwhash.stub.php @@ -3,13 +3,7 @@ /** @generate-class-entries */ #if defined(HAVE_OPENSSL_ARGON2) -/** - * @var string - */ const PASSWORD_ARGON2I = "argon2i"; -/** - * @var string - */ const PASSWORD_ARGON2ID = "argon2id"; /** * @var int @@ -26,9 +20,6 @@ * @cvalue PHP_OPENSSL_PWHASH_THREADS */ const PASSWORD_ARGON2_DEFAULT_THREADS = UNKNOWN; -/** - * @var string - */ const PASSWORD_ARGON2_PROVIDER = "openssl"; #endif diff --git a/ext/openssl/openssl_pwhash_arginfo.h b/ext/openssl/openssl_pwhash_arginfo.h index b4213158a169a..13ce9203f5c32 100644 --- a/ext/openssl/openssl_pwhash_arginfo.h +++ b/ext/openssl/openssl_pwhash_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: b6056170a5c8f1a9582c5eef9261a0bd02f7a7e1 */ + * Stub hash: 23ee957ba4945be3a21db58051e548729c3ff44e */ static void register_openssl_pwhash_symbols(int module_number) { diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 67522f3d34717..92ccd9a546f9e 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -70,15 +70,24 @@ struct php_openssl_errors { int bottom; }; -ZEND_BEGIN_MODULE_GLOBALS(openssl) - struct php_openssl_errors *errors; - struct php_openssl_errors *errors_mark; +struct php_openssl_libctx { #if PHP_OPENSSL_API_VERSION >= 0x30000 OSSL_LIB_CTX *libctx; - char *propq; + OSSL_LIB_CTX *default_libctx; + OSSL_LIB_CTX *custom_libctx; #endif + char *propq; +}; + +ZEND_BEGIN_MODULE_GLOBALS(openssl) + struct php_openssl_errors *errors; + struct php_openssl_errors *errors_mark; + struct php_openssl_libctx ctx; ZEND_END_MODULE_GLOBALS(openssl) +#define PHP_OPENSSL_LIBCTX OPENSSL_G(ctx).libctx +#define PHP_OPENSSL_PROPQ OPENSSL_G(ctx).propq + #define OPENSSL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(openssl, v) #if defined(ZTS) && defined(COMPILE_DL_OPENSSL) diff --git a/ext/openssl/php_openssl_backend.h b/ext/openssl/php_openssl_backend.h index 69317e3c7833b..35af52c6c8324 100644 --- a/ext/openssl/php_openssl_backend.h +++ b/ext/openssl/php_openssl_backend.h @@ -190,7 +190,17 @@ X509_STORE * php_openssl_setup_verify(zval * calist, uint32_t arg_num); STACK_OF(X509) * php_openssl_load_all_certs_from_file( char *cert_file, size_t cert_file_len, uint32_t arg_num); EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req); -zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t key_size); +zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t requested_key_size); + +X509 *php_openssl_pem_read_asn1_bio_x509(BIO *in); +X509 *php_openssl_pem_read_bio_x509(BIO *in); +X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in); +EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in); +EVP_PKEY *php_openssl_pem_read_bio_private_key(BIO *in, pem_password_cb *cb, void *u); +PKCS7 *php_openssl_pem_read_bio_pkcs7(BIO *in); +CMS_ContentInfo *php_openssl_pem_read_bio_cms(BIO *in); +CMS_ContentInfo *php_openssl_d2i_bio_cms(BIO *in); +CMS_ContentInfo *php_openssl_smime_read_cms(BIO *bio, BIO **bcont); #define PHP_SSL_REQ_INIT(req) memset(req, 0, sizeof(*req)) #define PHP_SSL_REQ_DISPOSE(req) php_openssl_dispose_config(req) @@ -237,10 +247,8 @@ void php_openssl_backend_init_common(void); void php_openssl_backend_gshutdown(void); void php_openssl_backend_shutdown(void); -#if PHP_OPENSSL_API_VERSION >= 0x30000 -void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq); -void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq); -#endif +void php_openssl_backend_init_libctx(struct php_openssl_libctx *ctx); +void php_openssl_backend_destroy_libctx(struct php_openssl_libctx *ctx); const char *php_openssl_get_conf_filename(void); @@ -368,4 +376,6 @@ zend_result php_openssl_cipher_update(const EVP_CIPHER *cipher_type, const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *method); +CONF *php_openssl_nconf_new(void); + #endif diff --git a/ext/openssl/tests/bug80770.phpt b/ext/openssl/tests/bug80770.phpt new file mode 100644 index 0000000000000..9100aaa5aa188 --- /dev/null +++ b/ext/openssl/tests/bug80770.phpt @@ -0,0 +1,83 @@ +--TEST-- +Bug #80770: SNI_server_certs does not inherit peer verification options +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'SNI_server_certs' => [ + "cs.php.net" => __DIR__ . "/sni_server_cs.pem", + "uk.php.net" => __DIR__ . "/sni_server_uk.pem", + "us.php.net" => __DIR__ . "/sni_server_us.pem" + ], + 'verify_peer' => true, + 'cafile' => '%s', + 'capture_peer_cert' => true, + 'verify_peer_name' => false, + 'security_level' => 0, + ]]); + $server = stream_socket_server('tcp://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + $client = stream_socket_accept($server, 30); + if ($client) { + $success = stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER); + if ($success) { + $options = stream_context_get_options($client); + $hasCert = isset($options['ssl']['peer_certificate']); + phpt_notify(message: $hasCert ? "CLIENT_CERT_CAPTURED" : "NO_CLIENT_CERT"); + } else { + phpt_notify(message: "TLS_HANDSHAKE_FAILED"); + } + } else { + phpt_notify(message: "ACCEPT_FAILED"); + } +CODE; +$serverCode = sprintf($serverCode, $caCertFile); + +$clientCode = <<<'CODE' + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'local_cert' => '%s', + 'peer_name' => 'cs.php.net', + 'security_level' => 0, + ]]); + $client = stream_socket_client("tcp://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client) { + stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); + } + + $result = phpt_wait(); + echo trim($result); +CODE; +$clientCode = sprintf($clientCode, $clientCertFile); + +include 'CertificateGenerator.inc'; + +// Generate CA and client certificate signed by that CA +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveCaCert($caCertFile); +$certificateGenerator->saveNewCertAsFileWithKey('Bug80770 Test Client', $clientCertFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +CLIENT_CERT_CAPTURED diff --git a/ext/openssl/tests/check_default_conf_path.phpt b/ext/openssl/tests/check_default_conf_path.phpt index 4590ef7804dad..267bebe16c1fa 100644 --- a/ext/openssl/tests/check_default_conf_path.phpt +++ b/ext/openssl/tests/check_default_conf_path.phpt @@ -21,7 +21,7 @@ ob_end_clean(); preg_match(",Openssl default config [^ ]* (.*),", $info, $m); if (isset($m[1])) { - var_dump(str_replace('/', '\\', strtolower($m[1]))); + var_dump(str_replace('\\/', '\\', strtolower($m[1]))); } else { echo $info; } diff --git a/ext/openssl/tests/gh19245.phpt b/ext/openssl/tests/gh19245.phpt new file mode 100644 index 0000000000000..13433cc42a325 --- /dev/null +++ b/ext/openssl/tests/gh19245.phpt @@ -0,0 +1,53 @@ +--TEST-- +GH-19245: Success error message on TLS stream accept failure +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'local_pk' => '%s', + ]]); + + $sock = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx); + phpt_notify_server_start($sock); + + $link = stream_socket_accept($sock); +CODE; + +$clientCode = <<<'CODE' + $serverUri = "ssl://{{ ADDR }}"; + $clientFlags = STREAM_CLIENT_CONNECT; + + $clientCtx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false + ]]); + + @stream_socket_client($serverUri, $errno, $errstr, 2, $clientFlags, $clientCtx); +CODE; + +$serverCode = sprintf($serverCodeTemplate, $baseDirCertFile . "\0test", $baseDirPkFile); +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); + +?> +--EXPECTF-- +PHP Warning: stream_socket_accept(): Path for local_cert in ssl stream context option must not contain any null bytes in %s +PHP Warning: stream_socket_accept(): Unable to get real path of certificate file `%scert.crt' in %s +PHP Warning: stream_socket_accept(): Failed to enable crypto in %s +PHP Warning: stream_socket_accept(): Accept failed: Cannot enable crypto in %s diff --git a/ext/openssl/tests/gh19369.phpt b/ext/openssl/tests/gh19369.phpt new file mode 100644 index 0000000000000..3568bbbfeaff1 --- /dev/null +++ b/ext/openssl/tests/gh19369.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-19369: openssl_sign with alias algorithms +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) diff --git a/ext/openssl/tests/gh19428.phpt b/ext/openssl/tests/gh19428.phpt new file mode 100644 index 0000000000000..373b49b525319 --- /dev/null +++ b/ext/openssl/tests/gh19428.phpt @@ -0,0 +1,45 @@ +--TEST-- +GH-19428: openssl_pkey_derive() DH with low key_length +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +Deprecated: openssl_pkey_derive(): the $key_length parameter is deprecated as it is either ignored or truncates the key in %s on line %d +bool(false) diff --git a/ext/openssl/tests/openssl_cms_encrypt_auth_env.phpt b/ext/openssl/tests/openssl_cms_encrypt_auth_env.phpt new file mode 100644 index 0000000000000..9b2086c78acf0 --- /dev/null +++ b/ext/openssl/tests/openssl_cms_encrypt_auth_env.phpt @@ -0,0 +1,34 @@ +--TEST-- +openssl_cms_encrypt() auth enveloped data tests +--EXTENSIONS-- +openssl +--SKIPIF-- += 3.0'); +?> +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) +Now is the winter of our discontent. diff --git a/ext/openssl/tests/openssl_cms_encrypt_basic.phpt b/ext/openssl/tests/openssl_cms_encrypt_basic.phpt index 14b5231fdd327..0ddda76d83a6a 100644 --- a/ext/openssl/tests/openssl_cms_encrypt_basic.phpt +++ b/ext/openssl/tests/openssl_cms_encrypt_basic.phpt @@ -5,13 +5,9 @@ openssl --FILE-- +--CLEAN-- + --EXPECT-- bool(true) bool(true) diff --git a/ext/openssl/tests/openssl_encrypt_cbc.phpt b/ext/openssl/tests/openssl_encrypt_cbc.phpt new file mode 100644 index 0000000000000..5ac526afaa09c --- /dev/null +++ b/ext/openssl/tests/openssl_encrypt_cbc.phpt @@ -0,0 +1,12 @@ +--TEST-- +openssl_encrypt() CBC and its alias +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +string(48) "7a654459353452676f6c6b6a446b75455a6c4c6b4f513d3d" +string(48) "7a654459353452676f6c6b6a446b75455a6c4c6b4f513d3d" diff --git a/ext/openssl/tests/openssl_libctx_with_zts_argon.phpt b/ext/openssl/tests/openssl_libctx_with_zts_argon.phpt new file mode 100644 index 0000000000000..13efcaa26b60b --- /dev/null +++ b/ext/openssl/tests/openssl_libctx_with_zts_argon.phpt @@ -0,0 +1,22 @@ +--TEST-- +openssl.libctx INI setting when Argon2 enabled and ZTS used +--EXTENSIONS-- +openssl +--INI-- +openssl.libctx = default +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Fatal error: PHP Startup: OpenSSL libctx "default" cannot be used in this configuration in Unknown on line 0 +string(6) "custom" diff --git a/ext/openssl/tests/openssl_libctx_without_zts_argon.phpt b/ext/openssl/tests/openssl_libctx_without_zts_argon.phpt new file mode 100644 index 0000000000000..f2fd64b7469d2 --- /dev/null +++ b/ext/openssl/tests/openssl_libctx_without_zts_argon.phpt @@ -0,0 +1,18 @@ +--TEST-- +openssl.libctx INI setting when Argon2 disable or ZTS not used +--EXTENSIONS-- +openssl +--INI-- +openssl.libctx = default +--SKIPIF-- + +--FILE-- + +--EXPECT-- +string(7) "default" diff --git a/ext/openssl/tests/openssl_pkey_derive_deprecated_key_length_param.phpt b/ext/openssl/tests/openssl_pkey_derive_deprecated_key_length_param.phpt new file mode 100644 index 0000000000000..b6a4c91675359 --- /dev/null +++ b/ext/openssl/tests/openssl_pkey_derive_deprecated_key_length_param.phpt @@ -0,0 +1,45 @@ +--TEST-- +openssl_pkey_derive() DH +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +Deprecated: openssl_pkey_derive(): the $key_length parameter is deprecated as it is either ignored or truncates the key in %s on line %d +string(512) "10aed66ad96a65f50543aa9adbc18ea169bf98521c682c49fb8b7daeb9e8fbe6b9a800199ffe1123cc36fc358829cbbc5d21bf1eb8ce3cf644538b357f478361a284c27fbe31fc94d431562786dd7314613cd70e6d76ca1ab3c1f31556ed07162f243dcc1a43ea98c454fb6e891eaec7a14158d54cd33d3fbbbc75f1ea8ff5deaab25d5deb657c7c43004252df301b195207d01614e7cb833e0e8d785ba2ecfe16ad7a9634784fdb8db8afe049476b58743575725ee99c761a59a7d7b9e709fff84c8d427e2bc07953a7c2408eb3f8f7e0ebc2f901c6889955874ae79a3de19921757d69424145a35dbe5af778b080dada55bdfce8fb0319f2de39110f58e05d" diff --git a/ext/openssl/tests/openssl_private_decrypt_digest.phpt b/ext/openssl/tests/openssl_private_decrypt_digest.phpt new file mode 100644 index 0000000000000..9bb07ba71eac1 --- /dev/null +++ b/ext/openssl/tests/openssl_private_decrypt_digest.phpt @@ -0,0 +1,57 @@ +--TEST-- +openssl_private_decrypt() with digest algorithm tests +--EXTENSIONS-- +openssl +--FILE-- +getMessage()); +} + +openssl_public_encrypt($data, $encrypted_pkcs1, $pubkey, OPENSSL_PKCS1_PADDING); +var_dump(openssl_private_decrypt($encrypted_pkcs1, $output_pkcs1, $privkey, OPENSSL_PKCS1_PADDING, "sha256")); +var_dump($output_pkcs1); +?> +--EXPECTF-- +bool(true) +string(56) "Testing openssl_private_decrypt() with digest algorithms" +bool(true) +string(56) "Testing openssl_private_decrypt() with digest algorithms" +bool(false) +NULL + +Warning: openssl_private_decrypt(): Unknown digest algorithm: invalid_hash in %s on line %d +bool(false) +NULL +string(85) "openssl_private_decrypt(): Argument #5 ($digest_algo) must not contain any null bytes" +bool(true) +string(56) "Testing openssl_private_decrypt() with digest algorithms" diff --git a/ext/openssl/tests/openssl_sign_basic.phpt b/ext/openssl/tests/openssl_sign_basic.phpt index 047028101893c..9d2edbec59f7a 100644 --- a/ext/openssl/tests/openssl_sign_basic.phpt +++ b/ext/openssl/tests/openssl_sign_basic.phpt @@ -8,11 +8,27 @@ $data = "Testing openssl_sign()"; $privkey = "file://" . __DIR__ . "/private_rsa_1024.key"; $wrong = "wrong"; -var_dump(openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256)); // no output +var_dump(openssl_sign($data, $sign1, $privkey, OPENSSL_ALGO_SHA256)); +var_dump(bin2hex($sign1)); +var_dump(openssl_sign($data, $sign2, $privkey, OPENSSL_ALGO_SHA256)); +var_dump($sign1 === $sign2); +var_dump(openssl_sign($data, $sign1, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING)); +var_dump(strlen($sign1)); +var_dump(openssl_sign($data, $sign2, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING)); +var_dump(strlen($sign2)); +var_dump($sign1 === $sign2); var_dump(openssl_sign($data, $sign, $wrong)); ?> --EXPECTF-- bool(true) +string(256) "5eff033d92208fcbf52edc9cbf6c9d4bd7c06b7b5a6a22c7d641d1494a09d6b0898d321c0a8fdb55c10b9bf25c2bb777c2b4660f867001f79879d089de7321a28df5f037cc02b68c47d1eb28d98a9199876961adb02524a489872a12fd3675db6a957d623ff04b9f715b565f516806cea247264c82a7569871dbd0b86cfe4689" +bool(true) +bool(true) +bool(true) +int(128) +bool(true) +int(128) +bool(false) Warning: openssl_sign(): Supplied key param cannot be coerced into a private key in %s on line %d bool(false) diff --git a/ext/openssl/tests/openssl_verify_basic.phpt b/ext/openssl/tests/openssl_verify_basic.phpt index 674a3c58a9ea3..1b28c1371083a 100644 --- a/ext/openssl/tests/openssl_verify_basic.phpt +++ b/ext/openssl/tests/openssl_verify_basic.phpt @@ -9,6 +9,10 @@ $privkey = "file://" . __DIR__ . "/private_rsa_1024.key"; $pubkey = "file://" . __DIR__ . "/public.key"; $wrong = "wrong"; + +openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING); +var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256, OPENSSL_PKCS1_PSS_PADDING)); +var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256)); openssl_sign($data, $sign, $privkey, OPENSSL_ALGO_SHA256); var_dump(openssl_verify($data, $sign, $pubkey, OPENSSL_ALGO_SHA256)); var_dump(openssl_verify($data, $sign, $privkey, OPENSSL_ALGO_SHA256)); @@ -18,6 +22,8 @@ var_dump(openssl_verify($wrong, $sign, $pubkey, OPENSSL_ALGO_SHA256)); ?> --EXPECTF-- int(1) +int(0) +int(1) Warning: openssl_verify(): Supplied key param cannot be coerced into a public key in %s on line %d bool(false) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index e728f647a3528..23f37355af568 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -23,10 +23,12 @@ #include "php.h" #include "ext/standard/file.h" -#include "ext/standard/url.h" +#include "ext/uri/php_uri.h" #include "streams/php_streams_int.h" #include "zend_smart_str.h" +#include "zend_exceptions.h" #include "php_openssl.h" +#include "php_openssl_backend.h" #include "php_network.h" #include #include @@ -237,7 +239,7 @@ static int php_openssl_handle_ssl_error(php_stream *stream, int nr_bytes, bool i char esbuf[512]; smart_str ebuf = {0}; unsigned long ecode; - int retry = 1; + bool retry = true; switch(err) { case SSL_ERROR_ZERO_RETURN: @@ -249,7 +251,7 @@ static int php_openssl_handle_ssl_error(php_stream *stream, int nr_bytes, bool i /* re-negotiation, or perhaps the SSL layer needs more * packets: retry in next iteration */ errno = EAGAIN; - retry = is_init ? 1 : sslsock->s.is_blocked; + retry = is_init ? true : sslsock->s.is_blocked; break; case SSL_ERROR_SYSCALL: if (ERR_peek_error() == 0) { @@ -850,7 +852,7 @@ static long php_openssl_load_stream_cafile(X509_STORE *cert_store, const char *c add_cert: { BIO_puts(buffer, line); efree(line); - cert = PEM_read_bio_X509(buffer, NULL, 0, NULL); + cert = php_openssl_pem_read_bio_x509(buffer); BIO_free(buffer); buffer_active = 0; if (cert && X509_STORE_add_cert(cert_store, cert)) { @@ -1324,7 +1326,8 @@ static SSL_CTX *php_openssl_create_sni_server_ctx(char *cert_path, char *key_pat } /* }}} */ -static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ +static zend_result php_openssl_enable_server_sni( + php_stream *stream, php_openssl_netstream_data_t *sslsock, bool verify_peer) { zval *val; zval *current; @@ -1445,6 +1448,12 @@ static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl return FAILURE; } + if (!verify_peer) { + php_openssl_disable_peer_verification(ctx, stream); + } else if (FAILURE == php_openssl_enable_peer_verification(ctx, stream)) { + return FAILURE; + } + sslsock->sni_certs[i].name = pestrdup(ZSTR_VAL(key), php_stream_is_persistent(stream)); sslsock->sni_certs[i].ctx = ctx; ++i; @@ -1455,7 +1464,6 @@ static zend_result php_openssl_enable_server_sni(php_stream *stream, php_openssl return SUCCESS; } -/* }}} */ static void php_openssl_enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ { @@ -1547,6 +1555,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, char *cipherlist = NULL; char *alpn_protocols = NULL; zval *val; + bool verify_peer = false; if (sslsock->ssl_handle) { if (sslsock->s.is_blocked) { @@ -1594,8 +1603,11 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, if (GET_VER_OPT("verify_peer") && !zend_is_true(val)) { php_openssl_disable_peer_verification(sslsock->ctx, stream); - } else if (FAILURE == php_openssl_enable_peer_verification(sslsock->ctx, stream)) { - return FAILURE; + } else { + verify_peer = true; + if (FAILURE == php_openssl_enable_peer_verification(sslsock->ctx, stream)) { + return FAILURE; + } } /* callback for the passphrase (for localcert) */ @@ -1694,7 +1706,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, #ifdef HAVE_TLS_SNI /* Enable server-side SNI */ - if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock) == FAILURE) { + if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock, verify_peer) == FAILURE) { return FAILURE; } #endif @@ -1796,7 +1808,7 @@ static int php_openssl_enable_crypto(php_stream *stream, if (cparam->inputs.activate && !sslsock->ssl_active) { struct timeval start_time, *timeout; - int blocked = sslsock->s.is_blocked, has_timeout = 0; + bool blocked = sslsock->s.is_blocked, has_timeout = false; #ifdef HAVE_TLS_SNI if (sslsock->is_client) { @@ -1936,8 +1948,8 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si int retry = 1; struct timeval start_time; struct timeval *timeout = NULL; - int began_blocked = sslsock->s.is_blocked; - int has_timeout = 0; + bool began_blocked = sslsock->s.is_blocked; + bool has_timeout = false; int nr_bytes = 0; /* prevent overflow in openssl */ @@ -1955,7 +1967,7 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si } if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec))) { - has_timeout = 1; + has_timeout = true; /* gettimeofday is not monotonic; using it here is not strictly correct */ gettimeofday(&start_time, NULL); } @@ -1977,7 +1989,7 @@ static ssize_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, si if (began_blocked) { php_openssl_set_blocking(sslsock, 1); } - sslsock->s.timeout_event = 1; + sslsock->s.timeout_event = true; return -1; } } @@ -2238,7 +2250,7 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ clisockdata->s.socket = clisock; #ifdef __linux__ /* O_NONBLOCK is not inherited on Linux */ - clisockdata->s.is_blocked = 1; + clisockdata->s.is_blocked = true; #endif xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+"); @@ -2263,6 +2275,12 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ php_stream_close(xparam->outputs.client); xparam->outputs.client = NULL; xparam->outputs.returncode = -1; + if (xparam->want_errortext) { + if (xparam->outputs.error_text) { + zend_string_free(xparam->outputs.error_text); + } + xparam->outputs.error_text = ZSTR_INIT_LITERAL("Cannot enable crypto", 0); + } } } } @@ -2369,8 +2387,8 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val int retry = 1; struct timeval start_time; struct timeval *timeout = NULL; - int began_blocked = sslsock->s.is_blocked; - int has_timeout = 0; + bool began_blocked = sslsock->s.is_blocked; + bool has_timeout = false; /* never use a timeout with non-blocking sockets */ if (began_blocked) { @@ -2382,7 +2400,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val } if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec))) { - has_timeout = 1; + has_timeout = true; /* gettimeofday is not monotonic; using it here is not strictly correct */ gettimeofday(&start_time, NULL); } @@ -2404,7 +2422,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val if (began_blocked) { php_openssl_set_blocking(sslsock, 1); } - sslsock->s.timeout_event = 1; + sslsock->s.timeout_event = true; return PHP_STREAM_OPTION_RETURN_ERR; } } @@ -2428,7 +2446,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val } /* Don't loop indefinitely in non-blocking mode if no data is available */ - if (began_blocked == 0 || !has_timeout) { + if (!began_blocked || !has_timeout) { alive = retry; break; } @@ -2610,23 +2628,29 @@ static zend_long php_openssl_get_crypto_method( /* }}} */ static char *php_openssl_get_url_name(const char *resourcename, - size_t resourcenamelen, int is_persistent) /* {{{ */ + size_t resourcenamelen, int is_persistent, php_stream_context *context) /* {{{ */ { - php_url *url; - if (!resourcename) { return NULL; } - url = php_url_parse_ex(resourcename, resourcenamelen); - if (!url) { + const php_uri_parser *uri_parser = php_stream_context_get_uri_parser("ssl", context); + if (uri_parser == NULL) { + zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name()); + return NULL; + } + + uri_internal_t *internal_uri = php_uri_parse(uri_parser, resourcename, resourcenamelen, true); + if (internal_uri == NULL) { return NULL; } - if (url->host) { - const char * host = ZSTR_VAL(url->host); - char * url_name = NULL; - size_t len = ZSTR_LEN(url->host); + char * url_name = NULL; + zval host_zv; + zend_result result = php_uri_get_host(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &host_zv); + if (result == SUCCESS && Z_TYPE(host_zv) == IS_STRING) { + const char * host = Z_STRVAL(host_zv); + size_t len = Z_STRLEN(host_zv); /* skip trailing dots */ while (len && host[len-1] == '.') { @@ -2636,13 +2660,12 @@ static char *php_openssl_get_url_name(const char *resourcename, if (len) { url_name = pestrndup(host, len, is_persistent); } - - php_url_free(url); - return url_name; } - php_url_free(url); - return NULL; + php_uri_free(internal_uri); + zval_ptr_dtor(&host_zv); + + return url_name; } /* }}} */ @@ -2658,7 +2681,7 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0); memset(sslsock, 0, sizeof(*sslsock)); - sslsock->s.is_blocked = 1; + sslsock->s.is_blocked = true; /* this timeout is used by standard stream funcs, therefore it should use the default value */ #ifdef _WIN32 sslsock->s.timeout.tv_sec = (long)FG(default_socket_timeout); @@ -2740,7 +2763,7 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, #endif } - sslsock->url_name = php_openssl_get_url_name(resourcename, resourcenamelen, !!persistent_id); + sslsock->url_name = php_openssl_get_url_name(resourcename, resourcenamelen, !!persistent_id, context); return stream; } diff --git a/ext/pcntl/config.m4 b/ext/pcntl/config.m4 index 3efa8a53cad1e..cfe6e80ca1103 100644 --- a/ext/pcntl/config.m4 +++ b/ext/pcntl/config.m4 @@ -13,7 +13,6 @@ if test "$PHP_PCNTL" != "no"; then forkx getcpuid getpriority - pidfd_open pset_bind pthread_set_qos_class_self_np rfork @@ -48,6 +47,9 @@ if test "$PHP_PCNTL" != "no"; then AC_CHECK_DECLS([SYS_waitid],,, [#include ]) + AC_CHECK_DECLS([SYS_pidfd_open],,, + [#include ]) + dnl if unsupported, -1 means automatically ENOSYS in this context AC_CACHE_CHECK([if sched_getcpu is supported], [php_cv_func_sched_getcpu], [AC_RUN_IFELSE([AC_LANG_SOURCE([ diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 1f061870ed453..4d1b5dff2e353 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -32,6 +32,7 @@ #include "php_signal.h" #include "php_ticks.h" #include "zend_fibers.h" +#include "main/php_main.h" #if defined(HAVE_GETPRIORITY) || defined(HAVE_SETPRIORITY) || defined(HAVE_WAIT3) #include @@ -125,18 +126,20 @@ typedef psetid_t cpu_set_t; #include #endif -#if defined(__linux__) && defined(HAVE_DECL_SYS_WAITID) && HAVE_DECL_SYS_WAITID == 1 && defined(HAVE_SYSCALL) -#define HAVE_LINUX_RAW_SYSCALL_WAITID 1 +#if defined(__linux__) && defined(HAVE_SYSCALL) +# include +# if defined(HAVE_DECL_SYS_WAITID) && HAVE_DECL_SYS_WAITID == 1 +# define HAVE_LINUX_RAW_SYSCALL_WAITID 1 +# endif +# if defined(HAVE_DECL_SYS_PIDFD_OPEN) && HAVE_DECL_SYS_PIDFD_OPEN == 1 +# define HAVE_LINUX_RAW_SYSCALL_PIDFD_OPEN 1 +# endif #endif #if defined(HAVE_LINUX_RAW_SYSCALL_WAITID) #include #endif -#if defined(HAVE_PIDFD_OPEN) || defined(HAVE_LINUX_RAW_SYSCALL_WAITID) -#include -#endif - #ifdef HAVE_FORKX #include #endif @@ -295,7 +298,7 @@ PHP_FUNCTION(pcntl_fork) } } else if (id == 0) { - zend_max_execution_timer_init(); + php_child_init(); } RETURN_LONG((zend_long) id); @@ -1353,7 +1356,7 @@ static void pcntl_signal_handler(int signo) PCNTL_G(head) = psig; } PCNTL_G(tail) = psig; - PCNTL_G(pending_signals) = 1; + PCNTL_G(pending_signals) = true; if (PCNTL_G(async_signals)) { zend_atomic_bool_store_ex(&EG(vm_interrupt), true); } @@ -1384,7 +1387,7 @@ void pcntl_signal_dispatch(void) zend_fiber_switch_block(); /* Prevent reentrant handler calls */ - PCNTL_G(processing_signal_queue) = 1; + PCNTL_G(processing_signal_queue) = true; queue = PCNTL_G(head); PCNTL_G(head) = NULL; /* simple stores are atomic */ @@ -1416,10 +1419,10 @@ void pcntl_signal_dispatch(void) queue = next; } - PCNTL_G(pending_signals) = 0; + PCNTL_G(pending_signals) = false; /* Re-enable queue */ - PCNTL_G(processing_signal_queue) = 0; + PCNTL_G(processing_signal_queue) = false; /* Re-enable fiber switching */ zend_fiber_switch_unblock(); @@ -1557,6 +1560,8 @@ PHP_FUNCTION(pcntl_rfork) default: php_error_docref(NULL, E_WARNING, "Error %d", errno); } + } else if (pid == 0) { + php_child_init(); } RETURN_LONG((zend_long) pid); @@ -1600,6 +1605,8 @@ PHP_FUNCTION(pcntl_forkx) default: php_error_docref(NULL, E_WARNING, "Error %d", errno); } + } else if (pid == 0) { + php_child_init(); } RETURN_LONG((zend_long) pid); @@ -1607,7 +1614,7 @@ PHP_FUNCTION(pcntl_forkx) #endif /* }}} */ -#ifdef HAVE_PIDFD_OPEN +#ifdef HAVE_LINUX_RAW_SYSCALL_PIDFD_OPEN // The `pidfd_open` syscall is available since 5.3 // and `setns` since 3.0. PHP_FUNCTION(pcntl_setns) diff --git a/ext/pcntl/php_pcntl.h b/ext/pcntl/php_pcntl.h index f09ccadcd3cdb..f2cc0d59195f4 100644 --- a/ext/pcntl/php_pcntl.h +++ b/ext/pcntl/php_pcntl.h @@ -43,12 +43,12 @@ struct php_pcntl_pending_signal { ZEND_BEGIN_MODULE_GLOBALS(pcntl) HashTable php_signal_table; - int processing_signal_queue; - struct php_pcntl_pending_signal *head, *tail, *spares; - int last_error; - volatile char pending_signals; + bool processing_signal_queue; + volatile bool pending_signals; bool async_signals; - unsigned num_signals; + uint8_t num_signals; + int last_error; + struct php_pcntl_pending_signal *head, *tail, *spares; ZEND_END_MODULE_GLOBALS(pcntl) #if defined(ZTS) && defined(COMPILE_DL_PCNTL) diff --git a/ext/pcre/config0.m4 b/ext/pcre/config0.m4 index d049cc538c0f5..4682080e0305e 100644 --- a/ext/pcre/config0.m4 +++ b/ext/pcre/config0.m4 @@ -96,8 +96,7 @@ else "]) AX_CHECK_COMPILE_FLAG([-Wno-implicit-fallthrough], - [PHP_PCRE_CFLAGS="$PHP_PCRE_CFLAGS -Wno-implicit-fallthrough"],, - [-Werror]) + [PHP_PCRE_CFLAGS="$PHP_PCRE_CFLAGS -Wno-implicit-fallthrough"]) PHP_PCRE_CFLAGS=m4_normalize([" $PHP_PCRE_CFLAGS diff --git a/ext/pcre/pcre2lib/pcre2.h b/ext/pcre/pcre2lib/pcre2.h index 6d1a8758ba966..7432608967398 100644 --- a/ext/pcre/pcre2lib/pcre2.h +++ b/ext/pcre/pcre2lib/pcre2.h @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE2_MAJOR 10 -#define PCRE2_MINOR 45 +#define PCRE2_MINOR 46 #define PCRE2_PRERELEASE -#define PCRE2_DATE 2025-02-05 +#define PCRE2_DATE 2025-08-27 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE2, the appropriate diff --git a/ext/pcre/pcre2lib/pcre2_match.c b/ext/pcre/pcre2lib/pcre2_match.c index 5adc03480522f..34a92eaa36ed3 100644 --- a/ext/pcre/pcre2lib/pcre2_match.c +++ b/ext/pcre/pcre2lib/pcre2_match.c @@ -5824,6 +5824,9 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, assert_accept_frame->offset_top * sizeof(PCRE2_SIZE)); Foffset_top = assert_accept_frame->offset_top; Fmark = assert_accept_frame->mark; + mb->end_subject = Lsaved_end_subject; + mb->true_end_subject = mb->end_subject + Ltrue_end_extra; + mb->moptions = Lsaved_moptions; break; } diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 9588f23d420c5..1bdfcd935cfd1 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -347,6 +347,11 @@ PDO_API void php_pdo_internal_construct_driver(INTERNAL_FUNCTION_PARAMETERS, zen } if (!strncmp(data_source, "uri:", sizeof("uri:")-1)) { + zend_error(E_DEPRECATED, "Looking up the DSN from a URI is deprecated due to possible security concerns with DSNs coming from remote URIs"); + if (EG(exception)) { + RETURN_THROWS(); + } + /* the specified URI holds connection details */ data_source = dsn_from_uri(data_source + sizeof("uri:")-1, alt_dsn, sizeof(alt_dsn)); if (!data_source) { @@ -1313,6 +1318,9 @@ static void cls_method_dtor(zval *el) /* {{{ */ { if (ZEND_MAP_PTR(func->common.run_time_cache)) { efree(ZEND_MAP_PTR(func->common.run_time_cache)); } + if (func->common.attributes) { + zend_hash_release(func->common.attributes); + } efree(func); } /* }}} */ @@ -1325,10 +1333,39 @@ static void cls_method_pdtor(zval *el) /* {{{ */ { if (ZEND_MAP_PTR(func->common.run_time_cache)) { pefree(ZEND_MAP_PTR(func->common.run_time_cache), 1); } + if (func->common.attributes) { + zend_hash_release(func->common.attributes); + } pefree(func, 1); } /* }}} */ +/* We cannot add #[Deprecated] attributes in @generate-function-entries stubs, + * and PDO drivers have no way to add them either, so we hard-code deprecation + * info here and add the attribute manually in pdo_hash_methods() */ +struct driver_specific_method_deprecation { + const char *old_name; + const char *new_name; +}; + +/* Methods deprecated in https://wiki.php.net/rfc/deprecations_php_8_5 + * "Deprecate driver specific PDO constants and methods" */ +static const struct driver_specific_method_deprecation driver_specific_method_deprecations[] = { + {"pgsqlCopyFromArray", "Pdo\\Pgsql::copyFromArray"}, + {"pgsqlCopyFromFile", "Pdo\\Pgsql::copyFromFile"}, + {"pgsqlCopyToArray", "Pdo\\Pgsql::copyToArray"}, + {"pgsqlCopyToFile", "Pdo\\Pgsql::copyToFile"}, + {"pgsqlGetNotify", "Pdo\\Pgsql::getNotify"}, + {"pgsqlGetPid", "Pdo\\Pgsql::getPid"}, + {"pgsqlLOBCreate", "Pdo\\Pgsql::lobCreate"}, + {"pgsqlLOBOpen", "Pdo\\Pgsql::lobOpen"}, + {"pgsqlLOBUnlink", "Pdo\\Pgsql::lobUnlink"}, + {"sqliteCreateAggregate", "Pdo\\Sqlite::createAggregate"}, + {"sqliteCreateCollation", "Pdo\\Sqlite::createCollation"}, + {"sqliteCreateFunction", "Pdo\\Sqlite::createFunction"}, + {NULL, NULL}, +}; + /* {{{ overloaded object handlers for PDO class */ bool pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind) { @@ -1366,6 +1403,7 @@ bool pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind) } else { func.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_NEVER_CACHE; } + func.fn_flags |= ZEND_ACC_DEPRECATED; func.doc_comment = NULL; if (funcs->arg_info) { zend_internal_function_info *info = (zend_internal_function_info*)funcs->arg_info; @@ -1394,8 +1432,36 @@ bool pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind) namelen = strlen(funcs->fname); lc_name = emalloc(namelen+1); zend_str_tolower_copy(lc_name, funcs->fname, namelen); - zend_hash_str_add_mem(dbh->cls_methods[kind], lc_name, namelen, &func, sizeof(func)); + zend_function *func_p = zend_hash_str_add_mem(dbh->cls_methods[kind], lc_name, namelen, &func, sizeof(func)); efree(lc_name); + + const char *new_name = NULL; + for (const struct driver_specific_method_deprecation *d = driver_specific_method_deprecations; + d->old_name; d++) { + if (strcmp(d->old_name, funcs->fname) == 0) { + new_name = d->new_name; + break; + } + } + if (new_name) { + uint32_t flags = dbh->is_persistent ? ZEND_ATTRIBUTE_PERSISTENT : 0; + zend_attribute *attr = zend_add_attribute( + &func_p->common.attributes, + ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), + 2, flags, 0, 0); + + attr->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR(&attr->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + + char *message; + size_t len = zend_spprintf(&message, 0, "use %s() instead", new_name); + zend_string *message_str = zend_string_init(message, len, dbh->is_persistent); + efree(message); + + attr->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + ZVAL_STR(&attr->args[1].value, message_str); + } + funcs++; } diff --git a/ext/pdo/php_pdo.h b/ext/pdo/php_pdo.h index 1618c78d62284..59789a04c73f2 100644 --- a/ext/pdo/php_pdo.h +++ b/ext/pdo/php_pdo.h @@ -18,6 +18,9 @@ #define PHP_PDO_H #include "zend.h" +#include "Zend/zend_compile.h" +#include "Zend/zend_API.h" +#include "Zend/zend_attributes.h" PHPAPI extern zend_module_entry pdo_module_entry; #define phpext_pdo_ptr &pdo_module_entry @@ -50,8 +53,47 @@ PHP_MINIT_FUNCTION(pdo); PHP_MSHUTDOWN_FUNCTION(pdo); PHP_MINFO_FUNCTION(pdo); -#define REGISTER_PDO_CLASS_CONST_LONG(const_name, value) \ - zend_declare_class_constant_long(php_pdo_get_dbh_ce(), const_name, sizeof(const_name)-1, (zend_long)value); +static inline void pdo_declare_deprecated_class_constant_long( + zend_class_entry *ce, const char *name, zend_long value, + zend_string *since, const char *message) { + + zval zvalue; + ZVAL_LONG(&zvalue, value); + + zend_string *name_str = zend_string_init_interned(name, strlen(name), true); + + zend_class_constant *constant = zend_declare_class_constant_ex( + ce, name_str, &zvalue, + ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL); + + zend_attribute *attr = zend_add_class_constant_attribute(ce, constant, + ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), + 1 + (message != NULL)); + + attr->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR(&attr->args[0].value, since); + + if (message) { + zend_string *message_str = zend_string_init_interned(message, strlen(message), true); + + attr->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + ZVAL_STR(&attr->args[1].value, message_str); + } +} + +/* Declare a constant deprecated in 8.5 */ +#define REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_85(const_name, value) \ + pdo_declare_deprecated_class_constant_long(php_pdo_get_dbh_ce(), \ + const_name, (zend_long)value, \ + ZSTR_KNOWN(ZEND_STR_8_DOT_5), NULL) + +/* Declare one of the constants deprecated in https://wiki.php.net/rfc/deprecations_php_8_5 + * "Deprecate driver specific PDO constants and methods" */ +#define REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(name, old_prefix, new_prefix, value) \ + pdo_declare_deprecated_class_constant_long(php_pdo_get_dbh_ce(), \ + old_prefix name, (zend_long)value, \ + ZSTR_KNOWN(ZEND_STR_8_DOT_5), \ + "use " new_prefix name " instead") #define LONG_CONST(c) (zend_long) c diff --git a/ext/pdo/tests/pdo_016.phpt b/ext/pdo/tests/pdo_016.phpt index 5b99930f2495c..2a5fa8d85f512 100644 --- a/ext/pdo/tests/pdo_016.phpt +++ b/ext/pdo/tests/pdo_016.phpt @@ -17,7 +17,7 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); } $db->exec('CREATE TABLE test016(idx int NOT NULL PRIMARY KEY, txt VARCHAR(20))'); diff --git a/ext/pdo/tests/pdo_016a.phpt b/ext/pdo/tests/pdo_016a.phpt index d7dcb2c65430b..2c0590594a84f 100644 --- a/ext/pdo/tests/pdo_016a.phpt +++ b/ext/pdo/tests/pdo_016a.phpt @@ -17,7 +17,7 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); } $db->exec('CREATE TABLE test016a(idx int NOT NULL PRIMARY KEY, txt VARCHAR(20))'); diff --git a/ext/pdo/tests/pdo_021.phpt b/ext/pdo/tests/pdo_021.phpt index 494ad3c39c50f..7ca3b075881f4 100644 --- a/ext/pdo/tests/pdo_021.phpt +++ b/ext/pdo/tests/pdo_021.phpt @@ -16,7 +16,7 @@ require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc'; $db = PDOTest::factory(); if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); } $db->exec('CREATE TABLE test021(id INT NOT NULL PRIMARY KEY, val VARCHAR(10), val2 VARCHAR(16))'); diff --git a/ext/pdo_dblib/pdo_dblib.c b/ext/pdo_dblib/pdo_dblib.c index b16208fbd8e78..9c59ddbc61849 100644 --- a/ext/pdo_dblib/pdo_dblib.c +++ b/ext/pdo_dblib/pdo_dblib.c @@ -190,15 +190,18 @@ PHP_RSHUTDOWN_FUNCTION(pdo_dblib) return SUCCESS; } +#define REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \ + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "DBLIB_", "Pdo\\Dblib::", value) + PHP_MINIT_FUNCTION(pdo_dblib) { - REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_CONNECTION_TIMEOUT", (long) PDO_DBLIB_ATTR_CONNECTION_TIMEOUT); - REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_QUERY_TIMEOUT", (long) PDO_DBLIB_ATTR_QUERY_TIMEOUT); - REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER", (long) PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER); - REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_VERSION", (long) PDO_DBLIB_ATTR_VERSION); - REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_TDS_VERSION", (long) PDO_DBLIB_ATTR_TDS_VERSION); - REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_SKIP_EMPTY_ROWSETS", (long) PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS); - REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_DATETIME_CONVERT", (long) PDO_DBLIB_ATTR_DATETIME_CONVERT); + REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_CONNECTION_TIMEOUT", (long) PDO_DBLIB_ATTR_CONNECTION_TIMEOUT); + REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_QUERY_TIMEOUT", (long) PDO_DBLIB_ATTR_QUERY_TIMEOUT); + REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_STRINGIFY_UNIQUEIDENTIFIER", (long) PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER); + REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_VERSION", (long) PDO_DBLIB_ATTR_VERSION); + REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_TDS_VERSION", (long) PDO_DBLIB_ATTR_TDS_VERSION); + REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SKIP_EMPTY_ROWSETS", (long) PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS); + REGISTER_PDO_DBLIB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_DATETIME_CONVERT", (long) PDO_DBLIB_ATTR_DATETIME_CONVERT); if (FAIL == dbinit()) { return FAILURE; diff --git a/ext/pdo_dblib/tests/bug_69592.phpt b/ext/pdo_dblib/tests/bug_69592.phpt index d7114e8fa09d6..711713775c446 100644 --- a/ext/pdo_dblib/tests/bug_69592.phpt +++ b/ext/pdo_dblib/tests/bug_69592.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_DBLIB: PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS for skip junk resultsets on SET NOCOUNT expression +PDO_DBLIB: Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS for skip junk resultsets on SET NOCOUNT expression --EXTENSIONS-- pdo_dblib --SKIPIF-- @@ -18,7 +18,7 @@ $sql = ' SELECT 0 AS [result] '; -var_dump($db->getAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS)); +var_dump($db->getAttribute(Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS)); $stmt = $db->query($sql); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -27,15 +27,15 @@ var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); $stmt->closeCursor(); -$db->setAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS, true); -var_dump($db->getAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS)); +$db->setAttribute(Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS, true); +var_dump($db->getAttribute(Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS)); $stmt = $db->query($sql); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); var_dump($stmt->nextRowset()); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); $stmt->closeCursor(); -var_dump($db->getAttribute(PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS)); +var_dump($db->getAttribute(Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS)); ?> --EXPECT-- diff --git a/ext/pdo_dblib/tests/bug_73396.phpt b/ext/pdo_dblib/tests/bug_73396.phpt index b2f96f8ec1c98..93dc66778a16a 100644 --- a/ext/pdo_dblib/tests/bug_73396.phpt +++ b/ext/pdo_dblib/tests/bug_73396.phpt @@ -6,7 +6,7 @@ pdo_dblib getAttribute(PDO::DBLIB_ATTR_TDS_VERSION), ['4.2', '4.6', '5.0', '6.0', '7.0'])) die('skip bigint type is unsupported by active TDS version'); +if (in_array($db->getAttribute(Pdo\Dblib::ATTR_TDS_VERSION), ['4.2', '4.6', '5.0', '6.0', '7.0'])) die('skip bigint type is unsupported by active TDS version'); ?> --FILE-- =1.1 function driver_supports_batch_statements_without_select($db) { - $version = $db->getAttribute(PDO::DBLIB_ATTR_VERSION); + $version = $db->getAttribute(Pdo\Dblib::ATTR_VERSION); return !strstartswith($version, 'freetds ') || !strstartswith($version, 'freetds v1.0'); } diff --git a/ext/pdo_dblib/tests/datetime2.phpt b/ext/pdo_dblib/tests/datetime2.phpt index e4f65048dd897..2b54361a30e59 100644 --- a/ext/pdo_dblib/tests/datetime2.phpt +++ b/ext/pdo_dblib/tests/datetime2.phpt @@ -6,7 +6,7 @@ pdo_dblib getAttribute(PDO::DBLIB_ATTR_TDS_VERSION), ['4.2', '4.6', '5.0', '6.0', '7.0', '7.1', '7.2'])) die('skip feature unsupported by this TDS version'); +if (in_array($db->getAttribute(Pdo\Dblib::ATTR_TDS_VERSION), ['4.2', '4.6', '5.0', '6.0', '7.0', '7.1', '7.2'])) die('skip feature unsupported by this TDS version'); ?> --FILE-- getAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT)); +var_dump($db->getAttribute(Pdo\Dblib::ATTR_DATETIME_CONVERT)); $stmt = $db->query($sql); var_dump($stmt->fetch(PDO::FETCH_ASSOC)); -$db->setAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT, 1); -var_dump($db->getAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT)); +$db->setAttribute(Pdo\Dblib::ATTR_DATETIME_CONVERT, 1); +var_dump($db->getAttribute(Pdo\Dblib::ATTR_DATETIME_CONVERT)); $stmt = $db->query($sql); var_dump($stmt->fetch(PDO::FETCH_ASSOC)); diff --git a/ext/pdo_dblib/tests/datetime_convert.phpt b/ext/pdo_dblib/tests/datetime_convert.phpt index ec858cf351c57..0934dd7f83e76 100644 --- a/ext/pdo_dblib/tests/datetime_convert.phpt +++ b/ext/pdo_dblib/tests/datetime_convert.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_DBLIB: PDO::DBLIB_ATTR_DATETIME_CONVERT +PDO_DBLIB: Pdo\Dblib::ATTR_DATETIME_CONVERT --EXTENSIONS-- pdo_dblib --SKIPIF-- @@ -15,14 +15,14 @@ $db = getDbConnection(); $sql = "SELECT convert(datetime, '20171027 10:22:44.135') AS [d]"; -var_dump($db->getAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT)); +var_dump($db->getAttribute(Pdo\Dblib::ATTR_DATETIME_CONVERT)); $stmt = $db->query($sql); var_dump($stmt->fetch(PDO::FETCH_ASSOC)); // assume default date format: %b %e %Y %I:%M:%S:%z%p -$db->setAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT, 1); -var_dump($db->getAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT)); +$db->setAttribute(Pdo\Dblib::ATTR_DATETIME_CONVERT, 1); +var_dump($db->getAttribute(Pdo\Dblib::ATTR_DATETIME_CONVERT)); $stmt = $db->query($sql); var_dump($stmt->fetch(PDO::FETCH_ASSOC)); diff --git a/ext/pdo_dblib/tests/dbtds.phpt b/ext/pdo_dblib/tests/dbtds.phpt index aa05606a93269..fb2402eec080c 100644 --- a/ext/pdo_dblib/tests/dbtds.phpt +++ b/ext/pdo_dblib/tests/dbtds.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_DBLIB: \PDO::DBLIB_ATTR_TDS_VERSION exposes a string or false +PDO_DBLIB: \Pdo\Dblib::ATTR_TDS_VERSION exposes a string or false --EXTENSIONS-- pdo_dblib --SKIPIF-- @@ -13,7 +13,7 @@ require __DIR__ . '/config.inc'; $db = getDbConnection(); -$version = $db->getAttribute(PDO::DBLIB_ATTR_TDS_VERSION); +$version = $db->getAttribute(Pdo\Dblib::ATTR_TDS_VERSION); var_dump((is_string($version) && strlen($version)) || $version === false); ?> diff --git a/ext/pdo_dblib/tests/dbversion.phpt b/ext/pdo_dblib/tests/dbversion.phpt index 44dd8f4a86dc3..aa61a26beeb23 100644 --- a/ext/pdo_dblib/tests/dbversion.phpt +++ b/ext/pdo_dblib/tests/dbversion.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_DBLIB: \PDO::DBLIB_ATTR_VERSION exposes a string +PDO_DBLIB: \Pdo\Dblib::ATTR_VERSION exposes a string --EXTENSIONS-- pdo_dblib --SKIPIF-- @@ -13,7 +13,7 @@ require __DIR__ . '/config.inc'; $db = getDbConnection(); -$version = $db->getAttribute(PDO::DBLIB_ATTR_VERSION); +$version = $db->getAttribute(Pdo\Dblib::ATTR_VERSION); var_dump(is_string($version) && strlen($version)); ?> diff --git a/ext/pdo_dblib/tests/php_8.5_deprecations.phpt b/ext/pdo_dblib/tests/php_8.5_deprecations.phpt new file mode 100644 index 0000000000000..bf0e84cb40800 --- /dev/null +++ b/ext/pdo_dblib/tests/php_8.5_deprecations.phpt @@ -0,0 +1,39 @@ +--TEST-- +PDO_dblib: PHP 8.5 deprecations +--EXTENSIONS-- +pdo_dblib +--FILE-- + +--EXPECTF-- +Deprecated: Constant PDO::DBLIB_ATTR_CONNECTION_TIMEOUT is deprecated since 8.5, use Pdo\Dblib::ATTR_CONNECTION_TIMEOUT instead in %s on line %d + +Deprecated: Constant PDO::DBLIB_ATTR_QUERY_TIMEOUT is deprecated since 8.5, use Pdo\Dblib::ATTR_QUERY_TIMEOUT instead in %s on line %d + +Deprecated: Constant PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER is deprecated since 8.5, use Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER instead in %s on line %d + +Deprecated: Constant PDO::DBLIB_ATTR_VERSION is deprecated since 8.5, use Pdo\Dblib::ATTR_VERSION instead in %s on line %d + +Deprecated: Constant PDO::DBLIB_ATTR_TDS_VERSION is deprecated since 8.5, use Pdo\Dblib::ATTR_TDS_VERSION instead in %s on line %d + +Deprecated: Constant PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS is deprecated since 8.5, use Pdo\Dblib::ATTR_SKIP_EMPTY_ROWSETS instead in %s on line %d + +Deprecated: Constant PDO::DBLIB_ATTR_DATETIME_CONVERT is deprecated since 8.5, use Pdo\Dblib::ATTR_DATETIME_CONVERT instead in %s on line %d +int(1000) +int(1001) +int(1002) +int(1003) +int(1004) +int(1005) +int(1006) diff --git a/ext/pdo_dblib/tests/stringify_uniqueidentifier.phpt b/ext/pdo_dblib/tests/stringify_uniqueidentifier.phpt index 86c94877c63c1..3e87b4790ca9e 100644 --- a/ext/pdo_dblib/tests/stringify_uniqueidentifier.phpt +++ b/ext/pdo_dblib/tests/stringify_uniqueidentifier.phpt @@ -6,7 +6,7 @@ pdo_dblib getAttribute(PDO::DBLIB_ATTR_TDS_VERSION), ['4.2', '4.6'])) die('skip feature unsupported by this TDS version'); +if (in_array($db->getAttribute(Pdo\Dblib::ATTR_TDS_VERSION), ['4.2', '4.6'])) die('skip feature unsupported by this TDS version'); ?> --FILE-- setAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, true); -var_dump(true === $db->getAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER)); -$db->setAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, false); -var_dump(false === $db->getAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER)); +$db->setAttribute(Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER, true); +var_dump(true === $db->getAttribute(Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER)); +$db->setAttribute(Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER, false); +var_dump(false === $db->getAttribute(Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER)); //-------------------------------------------------------------------------------- @@ -54,7 +54,7 @@ var_dump($row['guid'] === $testGUIDBinary); // TODO: something from PDO::ATTR_SERVER_VERSION, PDO::ATTR_CLIENT_VERSION or PDO::ATTR_SERVER_INFO should be used // to get TDS version and skip this test in this case. //-------------------------------------------------------------------------------- -$db->setAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, true); +$db->setAttribute(Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER, true); $stmt = $db->query($sql); $row = $stmt->fetch(PDO::FETCH_ASSOC); diff --git a/ext/pdo_dblib/tests/timeout.phpt b/ext/pdo_dblib/tests/timeout.phpt index 08e8ef54ecaba..5f935a3d01b89 100644 --- a/ext/pdo_dblib/tests/timeout.phpt +++ b/ext/pdo_dblib/tests/timeout.phpt @@ -33,7 +33,7 @@ if (!$stmt->execute()) { // pdo_dblib-specific timeout attribute, set after instance created, will control query timeout, causing this query to fail $db = getDbConnection(); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); -$db->setAttribute(PDO::DBLIB_ATTR_QUERY_TIMEOUT, 1); +$db->setAttribute(Pdo\Dblib::ATTR_QUERY_TIMEOUT, 1); $stmt = $db->prepare($sql); if (!$stmt->execute()) { echo "OK\n"; @@ -57,7 +57,7 @@ if (!$stmt->execute()) { } // pdo_dblib-specific timeout attribute will control query timeout, causing this query to fail -$db = getDbConnection(PDO::class, [PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT, PDO::DBLIB_ATTR_QUERY_TIMEOUT => 1]); +$db = getDbConnection(PDO::class, [PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT, Pdo\Dblib::ATTR_QUERY_TIMEOUT => 1]); $stmt = $db->prepare($sql); if (!$stmt->execute()) { echo "OK\n"; diff --git a/ext/pdo_dblib/tests/types.phpt b/ext/pdo_dblib/tests/types.phpt index a58a969c6f1b0..df04115fee9ee 100644 --- a/ext/pdo_dblib/tests/types.phpt +++ b/ext/pdo_dblib/tests/types.phpt @@ -16,7 +16,7 @@ $db = getDbConnection(); function get_expected_float_string() { global $db; - switch ($db->getAttribute(PDO::DBLIB_ATTR_TDS_VERSION)) { + switch ($db->getAttribute(Pdo\Dblib::ATTR_TDS_VERSION)) { case '5.0': case '6.0': case '7.0': diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 60a5e60e11bde..96b5cb1da1240 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -87,7 +87,6 @@ static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zv struct tm t; ISC_TIME time; char timeBuf[80] = {0}; - char timeTzBuf[124] = {0}; if (fb_decode_time_tz(S->H->isc_status, timeTz, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer)) { return 1; } @@ -100,8 +99,8 @@ static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zv return 1; } - size_t time_tz_len = sprintf(timeTzBuf, "%s %s", timeBuf, timeZoneBuffer); - ZVAL_STRINGL(result, timeTzBuf, time_tz_len); + zend_string *time_tz_str = zend_strpprintf(0, "%s %s", timeBuf, timeZoneBuffer); + ZVAL_NEW_STR(result, time_tz_str); return 0; } @@ -115,7 +114,6 @@ static int get_formatted_timestamp_tz(pdo_stmt_t *stmt, const ISC_TIMESTAMP_TZ* struct tm t; ISC_TIMESTAMP ts; char timestampBuf[80] = {0}; - char timestampTzBuf[124] = {0}; if (fb_decode_timestamp_tz(S->H->isc_status, timestampTz, &year, &month, &day, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer)) { return 1; } @@ -130,8 +128,8 @@ static int get_formatted_timestamp_tz(pdo_stmt_t *stmt, const ISC_TIMESTAMP_TZ* return 1; } - size_t timestamp_tz_len = sprintf(timestampTzBuf, "%s %s", timestampBuf, timeZoneBuffer); - ZVAL_STRINGL(result, timestampTzBuf, timestamp_tz_len); + zend_string *timestamp_tz_str = zend_strpprintf(0, "%s %s", timestampBuf, timeZoneBuffer); + ZVAL_NEW_STR(result, timestamp_tz_str); return 0; } diff --git a/ext/pdo_firebird/pdo_firebird.c b/ext/pdo_firebird/pdo_firebird.c index 0fbdb7f8c97c5..abc43dd3ad587 100644 --- a/ext/pdo_firebird/pdo_firebird.c +++ b/ext/pdo_firebird/pdo_firebird.c @@ -55,11 +55,14 @@ zend_module_entry pdo_firebird_module_entry = { /* {{{ */ ZEND_GET_MODULE(pdo_firebird) #endif +#define REGISTER_PDO_FB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \ + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "FB_", "Pdo\\Firebird::", value) + PHP_MINIT_FUNCTION(pdo_firebird) /* {{{ */ { - REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_DATE_FORMAT", (zend_long) PDO_FB_ATTR_DATE_FORMAT); - REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_TIME_FORMAT", (zend_long) PDO_FB_ATTR_TIME_FORMAT); - REGISTER_PDO_CLASS_CONST_LONG("FB_ATTR_TIMESTAMP_FORMAT", (zend_long) PDO_FB_ATTR_TIMESTAMP_FORMAT); + REGISTER_PDO_FB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_DATE_FORMAT", (zend_long) PDO_FB_ATTR_DATE_FORMAT); + REGISTER_PDO_FB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_TIME_FORMAT", (zend_long) PDO_FB_ATTR_TIME_FORMAT); + REGISTER_PDO_FB_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_TIMESTAMP_FORMAT", (zend_long) PDO_FB_ATTR_TIMESTAMP_FORMAT); if (FAILURE == php_pdo_register_driver(&pdo_firebird_driver)) { return FAILURE; diff --git a/ext/pdo_firebird/tests/dialect_1.phpt b/ext/pdo_firebird/tests/dialect_1.phpt index c08b37bf552c1..9b934cd40ec0c 100644 --- a/ext/pdo_firebird/tests/dialect_1.phpt +++ b/ext/pdo_firebird/tests/dialect_1.phpt @@ -14,7 +14,7 @@ require("testdb.inc"); $dbh = getDbConnection(); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); -$dbh->setAttribute(PDO::FB_ATTR_TIMESTAMP_FORMAT, '%Y-%m-%d %H:%M:%S'); +$dbh->setAttribute(Pdo\Firebird::ATTR_TIMESTAMP_FORMAT, '%Y-%m-%d %H:%M:%S'); $sql = 'SELECT diff --git a/ext/pdo_firebird/tests/execute.phpt b/ext/pdo_firebird/tests/execute.phpt index 464c8c29a9c44..cb749956ecfb1 100644 --- a/ext/pdo_firebird/tests/execute.phpt +++ b/ext/pdo_firebird/tests/execute.phpt @@ -12,7 +12,7 @@ $dbh = getDbConnection(); var_dump($dbh->getAttribute(PDO::ATTR_CONNECTION_STATUS)); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); -$dbh->setAttribute(PDO::FB_ATTR_TIMESTAMP_FORMAT, '%Y-%m-%d %H:%M:%S'); +$dbh->setAttribute(Pdo\Firebird::ATTR_TIMESTAMP_FORMAT, '%Y-%m-%d %H:%M:%S'); $dbh->exec("CREATE TABLE test_execute (id SMALLINT NOT NULL PRIMARY KEY, text VARCHAR(32), datetime TIMESTAMP DEFAULT '2000-02-12' NOT NULL)"); diff --git a/ext/pdo_firebird/tests/gh18276.phpt b/ext/pdo_firebird/tests/gh18276.phpt index 610876166ccf7..5a1c4b4de295d 100644 --- a/ext/pdo_firebird/tests/gh18276.phpt +++ b/ext/pdo_firebird/tests/gh18276.phpt @@ -23,9 +23,9 @@ for ($i = 0; $i < 2; $i++) { ], ); // Avoid interned - $dbh->setAttribute(PDO::FB_ATTR_DATE_FORMAT, str_repeat('Y----m----d', random_int(1, 1))); - $dbh->setAttribute(PDO::FB_ATTR_TIME_FORMAT, str_repeat('H::::i::::s', random_int(1, 1))); - $dbh->setAttribute(PDO::FB_ATTR_TIMESTAMP_FORMAT, str_repeat('Y----m----d....H::::i::::s', random_int(1, 1))); + $dbh->setAttribute(Pdo\Firebird::ATTR_DATE_FORMAT, str_repeat('Y----m----d', random_int(1, 1))); + $dbh->setAttribute(Pdo\Firebird::ATTR_TIME_FORMAT, str_repeat('H::::i::::s', random_int(1, 1))); + $dbh->setAttribute(Pdo\Firebird::ATTR_TIMESTAMP_FORMAT, str_repeat('Y----m----d....H::::i::::s', random_int(1, 1))); unset($dbh); } diff --git a/ext/pdo_firebird/tests/php_8.5_deprecations.phpt b/ext/pdo_firebird/tests/php_8.5_deprecations.phpt new file mode 100644 index 0000000000000..6919dda408fd3 --- /dev/null +++ b/ext/pdo_firebird/tests/php_8.5_deprecations.phpt @@ -0,0 +1,23 @@ +--TEST-- +PDO_firebird: PHP 8.5 deprecations +--EXTENSIONS-- +pdo_firebird +--FILE-- + +--EXPECTF-- +Deprecated: Constant PDO::FB_ATTR_DATE_FORMAT is deprecated since 8.5, use Pdo\Firebird::ATTR_DATE_FORMAT instead in %s on line %d + +Deprecated: Constant PDO::FB_ATTR_TIME_FORMAT is deprecated since 8.5, use Pdo\Firebird::ATTR_TIME_FORMAT instead in %s on line %d + +Deprecated: Constant PDO::FB_ATTR_TIMESTAMP_FORMAT is deprecated since 8.5, use Pdo\Firebird::ATTR_TIMESTAMP_FORMAT instead in %s on line %d +int(1000) +int(1001) +int(1002) diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index f0a2a887a5c75..786bd9c606cd1 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -84,7 +84,7 @@ int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int lin "Cannot execute queries while other unbuffered queries are active. " "Consider using PDOStatement::fetchAll(). Alternatively, if your code " "is only ever going to run against mysql, you may enable query " - "buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.", + "buffering by setting the Pdo\\Mysql::ATTR_USE_BUFFERED_QUERY attribute.", dbh->is_persistent); } } else if (einfo->errcode == 2057) { diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c index 772022cdbe937..b45dafbf5d986 100644 --- a/ext/pdo_mysql/pdo_mysql.c +++ b/ext/pdo_mysql/pdo_mysql.c @@ -112,37 +112,40 @@ PHP_INI_END() /* true global environment */ +#define REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \ + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "MYSQL_", "Pdo\\Mysql::", value) + /* {{{ PHP_MINIT_FUNCTION */ static PHP_MINIT_FUNCTION(pdo_mysql) { REGISTER_INI_ENTRIES(); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_USE_BUFFERED_QUERY", (zend_long)PDO_MYSQL_ATTR_USE_BUFFERED_QUERY); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_LOCAL_INFILE", (zend_long)PDO_MYSQL_ATTR_LOCAL_INFILE); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_INIT_COMMAND", (zend_long)PDO_MYSQL_ATTR_INIT_COMMAND); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_USE_BUFFERED_QUERY", (zend_long)PDO_MYSQL_ATTR_USE_BUFFERED_QUERY); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_LOCAL_INFILE", (zend_long)PDO_MYSQL_ATTR_LOCAL_INFILE); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_INIT_COMMAND", (zend_long)PDO_MYSQL_ATTR_INIT_COMMAND); #ifndef PDO_USE_MYSQLND - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_MAX_BUFFER_SIZE", (zend_long)PDO_MYSQL_ATTR_MAX_BUFFER_SIZE); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_READ_DEFAULT_FILE", (zend_long)PDO_MYSQL_ATTR_READ_DEFAULT_FILE); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_READ_DEFAULT_GROUP", (zend_long)PDO_MYSQL_ATTR_READ_DEFAULT_GROUP); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_MAX_BUFFER_SIZE", (zend_long)PDO_MYSQL_ATTR_MAX_BUFFER_SIZE); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_READ_DEFAULT_FILE", (zend_long)PDO_MYSQL_ATTR_READ_DEFAULT_FILE); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_READ_DEFAULT_GROUP", (zend_long)PDO_MYSQL_ATTR_READ_DEFAULT_GROUP); #endif - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_COMPRESS", (zend_long)PDO_MYSQL_ATTR_COMPRESS); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_DIRECT_QUERY", (zend_long)PDO_ATTR_EMULATE_PREPARES); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_FOUND_ROWS", (zend_long)PDO_MYSQL_ATTR_FOUND_ROWS); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_IGNORE_SPACE", (zend_long)PDO_MYSQL_ATTR_IGNORE_SPACE); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_KEY", (zend_long)PDO_MYSQL_ATTR_SSL_KEY); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CERT", (zend_long)PDO_MYSQL_ATTR_SSL_CERT); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CA", (zend_long)PDO_MYSQL_ATTR_SSL_CA); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CAPATH", (zend_long)PDO_MYSQL_ATTR_SSL_CAPATH); - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_CIPHER", (zend_long)PDO_MYSQL_ATTR_SSL_CIPHER); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_COMPRESS", (zend_long)PDO_MYSQL_ATTR_COMPRESS); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_DIRECT_QUERY", (zend_long)PDO_ATTR_EMULATE_PREPARES); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_FOUND_ROWS", (zend_long)PDO_MYSQL_ATTR_FOUND_ROWS); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_IGNORE_SPACE", (zend_long)PDO_MYSQL_ATTR_IGNORE_SPACE); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SSL_KEY", (zend_long)PDO_MYSQL_ATTR_SSL_KEY); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SSL_CERT", (zend_long)PDO_MYSQL_ATTR_SSL_CERT); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SSL_CA", (zend_long)PDO_MYSQL_ATTR_SSL_CA); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SSL_CAPATH", (zend_long)PDO_MYSQL_ATTR_SSL_CAPATH); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SSL_CIPHER", (zend_long)PDO_MYSQL_ATTR_SSL_CIPHER); #if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND) - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SERVER_PUBLIC_KEY", (zend_long)PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SERVER_PUBLIC_KEY", (zend_long)PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY); #endif - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_MULTI_STATEMENTS", (zend_long)PDO_MYSQL_ATTR_MULTI_STATEMENTS); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_MULTI_STATEMENTS", (zend_long)PDO_MYSQL_ATTR_MULTI_STATEMENTS); #ifdef PDO_USE_MYSQLND - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SSL_VERIFY_SERVER_CERT", (zend_long)PDO_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_SSL_VERIFY_SERVER_CERT", (zend_long)PDO_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT); #endif #if MYSQL_VERSION_ID >= 80021 || defined(PDO_USE_MYSQLND) - REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_LOCAL_INFILE_DIRECTORY", (zend_long)PDO_MYSQL_ATTR_LOCAL_INFILE_DIRECTORY); + REGISTER_PDO_MYSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_LOCAL_INFILE_DIRECTORY", (zend_long)PDO_MYSQL_ATTR_LOCAL_INFILE_DIRECTORY); #endif #ifdef PDO_USE_MYSQLND diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h index ae77193afcfa9..ec49d6c311c34 100644 --- a/ext/pdo_mysql/php_pdo_mysql_int.h +++ b/ext/pdo_mysql/php_pdo_mysql_int.h @@ -78,7 +78,7 @@ ZEND_BEGIN_MODULE_GLOBALS(pdo_mysql) /* dummy member so we get at least one member in the struct * and avoids build errors. */ - void *dummymemmber; + void *dummymember; #endif ZEND_END_MODULE_GLOBALS(pdo_mysql) diff --git a/ext/pdo_mysql/tests/bug66528.phpt b/ext/pdo_mysql/tests/bug66528.phpt index 31ae2f42e3a9d..4bddfc9dfcf15 100644 --- a/ext/pdo_mysql/tests/bug66528.phpt +++ b/ext/pdo_mysql/tests/bug66528.phpt @@ -13,7 +13,7 @@ require_once __DIR__ . '/inc/mysql_pdo_test.inc'; $dbh = MySQLPDOTest::factory(); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -$dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); +$dbh->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); $dbh->exec('CREATE TABLE test_66528 (a INT) ENGINE=InnoDB'); $dbh->beginTransaction(); @@ -46,6 +46,6 @@ $db = MySQLPDOTest::factory(); $db->exec('DROP TABLE IF EXISTS test_66528'); ?> --EXPECT-- -SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. -SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. -SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. +SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. +SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. +SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. diff --git a/ext/pdo_mysql/tests/bug67004.phpt b/ext/pdo_mysql/tests/bug67004.phpt index 019be3fec9dec..39e19a9ed22c4 100644 --- a/ext/pdo_mysql/tests/bug67004.phpt +++ b/ext/pdo_mysql/tests/bug67004.phpt @@ -14,7 +14,7 @@ $dbh = MySQLPDOTest::factory(); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); -$dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); +$dbh->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $dbh->prepare("SELECT ?"); diff --git a/ext/pdo_mysql/tests/bug68371.phpt b/ext/pdo_mysql/tests/bug68371.phpt index 146b8e4684d26..5b5152dd054a9 100644 --- a/ext/pdo_mysql/tests/bug68371.phpt +++ b/ext/pdo_mysql/tests/bug68371.phpt @@ -16,7 +16,7 @@ $pdo->setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $attrs = [ // Extensive test: default value and set+get values PDO::ATTR_EMULATE_PREPARES => array(null, true, false), - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => array(null, false, true), + Pdo\Mysql::ATTR_USE_BUFFERED_QUERY => array(null, false, true), // Just test the default PDO::ATTR_AUTOCOMMIT => [null], diff --git a/ext/pdo_mysql/tests/bug70389.phpt b/ext/pdo_mysql/tests/bug70389.phpt index b4f6bf1afeb48..a8bbab8cc16e0 100644 --- a/ext/pdo_mysql/tests/bug70389.phpt +++ b/ext/pdo_mysql/tests/bug70389.phpt @@ -11,8 +11,8 @@ MySQLPDOTest::skip(); true, - PDO::MYSQL_ATTR_LOCAL_INFILE => true, + Pdo\Mysql::ATTR_FOUND_ROWS => true, + Pdo\Mysql::ATTR_LOCAL_INFILE => true, PDO::ATTR_PERSISTENT => true, ]; diff --git a/ext/pdo_mysql/tests/bug71145.phpt b/ext/pdo_mysql/tests/bug71145.phpt index 0c6f1a549dfb9..b25207152666f 100644 --- a/ext/pdo_mysql/tests/bug71145.phpt +++ b/ext/pdo_mysql/tests/bug71145.phpt @@ -13,7 +13,7 @@ require_once __DIR__ . '/inc/mysql_pdo_test.inc'; $attr = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; SET SESSION sql_mode=traditional', + Pdo\Mysql::ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; SET SESSION sql_mode=traditional', PDO::ATTR_STRINGIFY_FETCHES => true, ]; diff --git a/ext/pdo_mysql/tests/bug71569.phpt b/ext/pdo_mysql/tests/bug71569.phpt index fe50b669d845b..975474dd55878 100644 --- a/ext/pdo_mysql/tests/bug71569.phpt +++ b/ext/pdo_mysql/tests/bug71569.phpt @@ -13,7 +13,7 @@ require_once __DIR__ . '/inc/mysql_pdo_test.inc'; try { new PDO(PDO_MYSQL_TEST_DSN, PDO_MYSQL_TEST_USER, PDO_MYSQL_TEST_PASS, [ - PDO::MYSQL_ATTR_INIT_COMMAND => null, + Pdo\Mysql::ATTR_INIT_COMMAND => null, ]); } catch (PDOException $e) { echo $e->getMessage(); diff --git a/ext/pdo_mysql/tests/bug79375.phpt b/ext/pdo_mysql/tests/bug79375.phpt index fb118f1db2d53..07ccd183d45f1 100644 --- a/ext/pdo_mysql/tests/bug79375.phpt +++ b/ext/pdo_mysql/tests/bug79375.phpt @@ -52,7 +52,7 @@ function testPrepareExecute(PDO $db, string $name) { } function testUnbuffered(PDO $db, string $name) { - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); $db->exec("SET innodb_lock_wait_timeout = 1"); $db->exec("START TRANSACTION"); $query = "SELECT first FROM test_79375 WHERE first = 1 FOR UPDATE"; diff --git a/ext/pdo_mysql/tests/bug80458.phpt b/ext/pdo_mysql/tests/bug80458.phpt index aecdca6674ccb..a425c69658e15 100644 --- a/ext/pdo_mysql/tests/bug80458.phpt +++ b/ext/pdo_mysql/tests/bug80458.phpt @@ -97,7 +97,7 @@ var_dump($stmt5->fetchAll()); $db->exec("DROP PROCEDURE IF EXISTS {$procedure_ret}"); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); -$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); +$db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); $stmt = $db->prepare('DELETE FROM test_80458 WHERE first=15'); $stmt->execute(); diff --git a/ext/pdo_mysql/tests/bug80908.phpt b/ext/pdo_mysql/tests/bug80908.phpt index 52b7a40dbb3cc..c00c196d9a668 100644 --- a/ext/pdo_mysql/tests/bug80908.phpt +++ b/ext/pdo_mysql/tests/bug80908.phpt @@ -23,7 +23,7 @@ $db->exec('CREATE TABLE test_80908 (`id` BIGINT(20) UNSIGNED AUTO_INCREMENT, `na function testLastInsertId(PDO $db) { echo "Running test lastInsertId\n"; - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); try { $db->exec("INSERT INTO test_80908 (`name`) VALUES ('bar')"); $id = $db->lastInsertId(); diff --git a/ext/pdo_mysql/tests/bug_42499.phpt b/ext/pdo_mysql/tests/bug_42499.phpt index 6f1534859a0ca..b0c009259e00b 100644 --- a/ext/pdo_mysql/tests/bug_42499.phpt +++ b/ext/pdo_mysql/tests/bug_42499.phpt @@ -28,13 +28,13 @@ function bug_42499($db) { print "Emulated Prepared Statements...\n"; $db = MySQLPDOTest::factory(); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); -$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); +$db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 1); bug_42499($db); print "Native Prepared Statements...\n"; $db = MySQLPDOTest::factory(); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); -$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); +$db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 1); bug_42499($db); print "done!"; @@ -55,7 +55,7 @@ array(1) { } } -Warning: PDO::exec(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d +Warning: PDO::exec(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d Native Prepared Statements... array(1) { [0]=> @@ -65,5 +65,5 @@ array(1) { } } -Warning: PDO::exec(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d +Warning: PDO::exec(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d done! diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt index ba3054247c2b6..2437e7ca12d16 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt @@ -44,11 +44,11 @@ MySQLPDOTest::skip(); PDO::ATTR_TIMEOUT => 'PDO::ATTR_TIMEOUT', PDO::ATTR_EMULATE_PREPARES => 'PDO::ATTR_EMULATE_PREPARES', - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => 'PDO::MYSQL_ATTR_USE_BUFFERED_QUERY', - PDO::MYSQL_ATTR_LOCAL_INFILE => 'PDO::MYSQL_ATTR_LOCAL_INFILE', - PDO::MYSQL_ATTR_DIRECT_QUERY => 'PDO::MYSQL_ATTR_DIRECT_QUERY', + Pdo\Mysql::ATTR_USE_BUFFERED_QUERY => 'Pdo\Mysql::ATTR_USE_BUFFERED_QUERY', + Pdo\Mysql::ATTR_LOCAL_INFILE => 'Pdo\Mysql::ATTR_LOCAL_INFILE', + Pdo\Mysql::ATTR_DIRECT_QUERY => 'Pdo\Mysql::ATTR_DIRECT_QUERY', - PDO::MYSQL_ATTR_INIT_COMMAND => 'PDO::MYSQL_ATTR_INIT_COMMAND', + Pdo\Mysql::ATTR_INIT_COMMAND => 'Pdo\Mysql::ATTR_INIT_COMMAND', PDO::ATTR_EMULATE_PREPARES => 'PDO::ATTR_EMULATE_PREPARES', ]; @@ -58,12 +58,12 @@ MySQLPDOTest::skip(); /* TODO - why is this a valid option if getAttribute() does not support it?! */ PDO::ATTR_TIMEOUT => false, PDO::ATTR_EMULATE_PREPARES => true, - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, + Pdo\Mysql::ATTR_USE_BUFFERED_QUERY => true, /* TODO getAttribute() does not handle it */ - PDO::MYSQL_ATTR_LOCAL_INFILE => false, + Pdo\Mysql::ATTR_LOCAL_INFILE => false, /* TODO getAttribute() does not handle it */ - PDO::MYSQL_ATTR_DIRECT_QUERY => true, - PDO::MYSQL_ATTR_INIT_COMMAND => '', + Pdo\Mysql::ATTR_DIRECT_QUERY => true, + Pdo\Mysql::ATTR_INIT_COMMAND => '', ]; try { @@ -108,56 +108,56 @@ MySQLPDOTest::skip(); if (!is_object($db = new PDO($dsn, $user, $pass, array(PDO::ATTR_TIMEOUT => -PHP_INT_MAX)))) printf("[008] ATTR_TIMEOUT should be accepted\n"); - /* TODO: Its ugly that PDO::ATTR_EMULATE_PREPARES == PDO::MYSQL_ATTR_DIRECT_QUERY */ + /* TODO: Its ugly that PDO::ATTR_EMULATE_PREPARES == Pdo\Mysql::ATTR_DIRECT_QUERY */ $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => true)); if (!is_object($db)) printf("[009] ATTR_EMULATE_PREPARES should be accepted and on\n"); if (!$db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) printf("[010] [TODO][CHANGEREQUEST] ATTR_EMULATE_PREPARES should be on\n"); - if (!$db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) - printf("[011] As PDO::MYSQL_ATTR_DIRECT_QUERY == PDO::ATTR_EMULATE_PREPARES - and PDO::ATTR_EMULATE_PREPARES overrules the other, PDO::MYSQL_ATTR_DIRECT_QUERY should be on\n"); + if (!$db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) + printf("[011] As Pdo\Mysql::ATTR_DIRECT_QUERY == PDO::ATTR_EMULATE_PREPARES + and PDO::ATTR_EMULATE_PREPARES overrules the other, Pdo\Mysql::ATTR_DIRECT_QUERY should be on\n"); $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => false)); if (!is_object($db)) printf("[012] ATTR_EMULATE_PREPARES should be accepted and on\n"); if ($db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) printf("[013] [TODO][CHANGEREQUEST] ATTR_EMULATE_PREPARES should be off\n"); - if ($db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) - printf("[014] As PDO::MYSQL_ATTR_DIRECT_QUERY == PDO::ATTR_EMULATE_PREPARES - and PDO::ATTR_EMULATE_PREPARES overrules the other, PDO::MYSQL_ATTR_DIRECT_QUERY should be off\n"); + if ($db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) + printf("[014] As Pdo\Mysql::ATTR_DIRECT_QUERY == PDO::ATTR_EMULATE_PREPARES + and PDO::ATTR_EMULATE_PREPARES overrules the other, Pdo\Mysql::ATTR_DIRECT_QUERY should be off\n"); - // PDO::ATTR_EMULATE_PREPARES overrules PDO::MYSQL_ATTR_DIRECT_QUERY + // PDO::ATTR_EMULATE_PREPARES overrules Pdo\Mysql::ATTR_DIRECT_QUERY // TODO: is it clever that a generic setting overrules a specific setting? - $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => true, PDO::MYSQL_ATTR_DIRECT_QUERY => false)); + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => true, Pdo\Mysql::ATTR_DIRECT_QUERY => false)); if (!$db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) printf("[015] PDO::ATTR_EMULATE_PREPARES should be on\n"); - if (!$db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) - printf("[016] PDO::MYSQL_ATTR_DIRECT_QUERY should be on\n"); + if (!$db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) + printf("[016] Pdo\Mysql::ATTR_DIRECT_QUERY should be on\n"); - $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => false, PDO::MYSQL_ATTR_DIRECT_QUERY => true)); + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => false, Pdo\Mysql::ATTR_DIRECT_QUERY => true)); if ($db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) printf("[017] PDO::ATTR_EMULATE_PREPARES should be off\n"); - if ($db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) - printf("[018] PDO::MYSQL_ATTR_DIRECT_QUERY should be off\n"); + if ($db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) + printf("[018] Pdo\Mysql::ATTR_DIRECT_QUERY should be off\n"); - set_option_and_check(19, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true, 'PDO::MYSQL_ATTR_USE_BUFFERED_QUERY'); - set_option_and_check(20, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false, 'PDO::MYSQL_ATTR_USE_BUFFERED_QUERY'); + set_option_and_check(19, Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true, 'Pdo\Mysql::ATTR_USE_BUFFERED_QUERY'); + set_option_and_check(20, Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false, 'Pdo\Mysql::ATTR_USE_BUFFERED_QUERY'); - set_option_and_check(21, PDO::MYSQL_ATTR_LOCAL_INFILE, true, 'PDO::MYSQL_ATTR_LOCAL_INFILE'); - set_option_and_check(22, PDO::MYSQL_ATTR_LOCAL_INFILE, false, 'PDO::MYSQL_ATTR_LOCAL_INFILE'); + set_option_and_check(21, Pdo\Mysql::ATTR_LOCAL_INFILE, true, 'Pdo\Mysql::ATTR_LOCAL_INFILE'); + set_option_and_check(22, Pdo\Mysql::ATTR_LOCAL_INFILE, false, 'Pdo\Mysql::ATTR_LOCAL_INFILE'); - set_option_and_check(23, PDO::MYSQL_ATTR_INIT_COMMAND, 'SET @a=1', 'PDO::MYSQL_ATTR_INIT_COMMAND'); - set_option_and_check(24, PDO::MYSQL_ATTR_INIT_COMMAND, '', 'PDO::MYSQL_ATTR_INIT_COMMAND'); - set_option_and_check(25, PDO::MYSQL_ATTR_INIT_COMMAND, 'INSERT INTO nonexistent(invalid) VALUES (1)', 'PDO::MYSQL_ATTR_INIT_COMMAND'); + set_option_and_check(23, Pdo\Mysql::ATTR_INIT_COMMAND, 'SET @a=1', 'Pdo\Mysql::ATTR_INIT_COMMAND'); + set_option_and_check(24, Pdo\Mysql::ATTR_INIT_COMMAND, '', 'Pdo\Mysql::ATTR_INIT_COMMAND'); + set_option_and_check(25, Pdo\Mysql::ATTR_INIT_COMMAND, 'INSERT INTO nonexistent(invalid) VALUES (1)', 'Pdo\Mysql::ATTR_INIT_COMMAND'); - set_option_and_check(33, PDO::MYSQL_ATTR_DIRECT_QUERY, true, 'PDO::MYSQL_ATTR_DIRECT_QUERY'); - set_option_and_check(34, PDO::MYSQL_ATTR_DIRECT_QUERY, false, 'PDO::MYSQL_ATTR_DIRECT_QUERY'); + set_option_and_check(33, Pdo\Mysql::ATTR_DIRECT_QUERY, true, 'Pdo\Mysql::ATTR_DIRECT_QUERY'); + set_option_and_check(34, Pdo\Mysql::ATTR_DIRECT_QUERY, false, 'Pdo\Mysql::ATTR_DIRECT_QUERY'); - if (defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) { - set_option_and_check(35, PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY, null, 'PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY'); + if (defined('Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY')) { + set_option_and_check(35, Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY, null, 'Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY'); // libmysqlclient returns the directory with a trailing slash. - // set_option_and_check(36, PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY, __DIR__, 'PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY'); + // set_option_and_check(36, Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY, __DIR__, 'Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY'); } } catch (PDOException $e) { printf("[001] %s, [%s] %s Line: %s\n", @@ -171,12 +171,12 @@ MySQLPDOTest::skip(); ?> --EXPECTF-- [003] [TODO][CHANGEREQUEST] Please, lets not ignore invalid options and bail out! -[003a] Expecting default value for 'PDO::MYSQL_ATTR_INIT_COMMAND' of ''/string, getAttribute() reports setting ''/boolean +[003a] Expecting default value for 'Pdo\Mysql::ATTR_INIT_COMMAND' of ''/string, getAttribute() reports setting ''/boolean [015] PDO::ATTR_EMULATE_PREPARES should be on -[016] PDO::MYSQL_ATTR_DIRECT_QUERY should be on +[016] Pdo\Mysql::ATTR_DIRECT_QUERY should be on [017] PDO::ATTR_EMULATE_PREPARES should be off -[018] PDO::MYSQL_ATTR_DIRECT_QUERY should be off -[023] Expecting 'SET @a=1'/string got ''/boolean' for options 'PDO::MYSQL_ATTR_INIT_COMMAND' +[018] Pdo\Mysql::ATTR_DIRECT_QUERY should be off +[023] Expecting 'SET @a=1'/string got ''/boolean' for options 'Pdo\Mysql::ATTR_INIT_COMMAND' [024] SQLSTATE[42000] [1065] Query was empty [025] SQLSTATE[42S02] [1146] Table '%s.nonexistent' doesn't exist done! diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct_options_libmysql.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct_options_libmysql.phpt index e3d8ee2db6583..c56ee9e5d1e98 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct_options_libmysql.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct_options_libmysql.phpt @@ -36,16 +36,16 @@ if (MySQLPDOTest::isPDOMySQLnd()) $pass = PDO_MYSQL_TEST_PASS; $valid_options = []; - $valid_options[PDO::MYSQL_ATTR_MAX_BUFFER_SIZE] = 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE'; - $valid_options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'PDO::MYSQL_ATTR_INIT_COMMAND'; - $valid_options[PDO::MYSQL_ATTR_READ_DEFAULT_FILE] = 'PDO::MYSQL_ATTR_READ_DEFAULT_FILE'; - $valid_options[PDO::MYSQL_ATTR_READ_DEFAULT_GROUP] = 'PDO::MYSQL_ATTR_READ_DEFAULT_GROUP'; + $valid_options[Pdo\Mysql::ATTR_MAX_BUFFER_SIZE] = 'Pdo\Mysql::ATTR_MAX_BUFFER_SIZE'; + $valid_options[Pdo\Mysql::ATTR_INIT_COMMAND] = 'Pdo\Mysql::ATTR_INIT_COMMAND'; + $valid_options[Pdo\Mysql::ATTR_READ_DEFAULT_FILE] = 'Pdo\Mysql::ATTR_READ_DEFAULT_FILE'; + $valid_options[Pdo\Mysql::ATTR_READ_DEFAULT_GROUP] = 'Pdo\Mysql::ATTR_READ_DEFAULT_GROUP'; - $defaults[PDO::MYSQL_ATTR_MAX_BUFFER_SIZE] = 1048576; + $defaults[Pdo\Mysql::ATTR_MAX_BUFFER_SIZE] = 1048576; /* TODO getAttribute() does not handle it */ - $defaults[PDO::MYSQL_ATTR_INIT_COMMAND] = ''; - $defaults[PDO::MYSQL_ATTR_READ_DEFAULT_FILE] = false; - $defaults[PDO::MYSQL_ATTR_READ_DEFAULT_GROUP] = false; + $defaults[Pdo\Mysql::ATTR_INIT_COMMAND] = ''; + $defaults[Pdo\Mysql::ATTR_READ_DEFAULT_FILE] = false; + $defaults[Pdo\Mysql::ATTR_READ_DEFAULT_GROUP] = false; $db = new PDO($dsn, $user, $pass); foreach ($valid_options as $option => $name) { @@ -60,19 +60,19 @@ if (MySQLPDOTest::isPDOMySQLnd()) } } - set_option_and_check(26, PDO::MYSQL_ATTR_READ_DEFAULT_FILE, true, 'PDO::MYSQL_ATTR_READ_DEFAULT_FILE'); - set_option_and_check(27, PDO::MYSQL_ATTR_READ_DEFAULT_FILE, false, 'PDO::MYSQL_ATTR_READ_DEFAULT_FILE'); + set_option_and_check(26, Pdo\Mysql::ATTR_READ_DEFAULT_FILE, true, 'Pdo\Mysql::ATTR_READ_DEFAULT_FILE'); + set_option_and_check(27, Pdo\Mysql::ATTR_READ_DEFAULT_FILE, false, 'Pdo\Mysql::ATTR_READ_DEFAULT_FILE'); - set_option_and_check(30, PDO::MYSQL_ATTR_MAX_BUFFER_SIZE, -1, 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE', true); - set_option_and_check(31, PDO::MYSQL_ATTR_MAX_BUFFER_SIZE, PHP_INT_MAX, 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE'); - set_option_and_check(32, PDO::MYSQL_ATTR_MAX_BUFFER_SIZE, 1, 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE'); + set_option_and_check(30, Pdo\Mysql::ATTR_MAX_BUFFER_SIZE, -1, 'Pdo\Mysql::ATTR_MAX_BUFFER_SIZE', true); + set_option_and_check(31, Pdo\Mysql::ATTR_MAX_BUFFER_SIZE, PHP_INT_MAX, 'Pdo\Mysql::ATTR_MAX_BUFFER_SIZE'); + set_option_and_check(32, Pdo\Mysql::ATTR_MAX_BUFFER_SIZE, 1, 'Pdo\Mysql::ATTR_MAX_BUFFER_SIZE'); print "done!\n"; ?> --EXPECT-- -Failed to getAttribute() for PDO::MYSQL_ATTR_INIT_COMMAND -Failed to getAttribute() for PDO::MYSQL_ATTR_READ_DEFAULT_FILE -Failed to getAttribute() for PDO::MYSQL_ATTR_READ_DEFAULT_GROUP -Failed to getAttribute() for PDO::MYSQL_ATTR_READ_DEFAULT_FILE -Failed to getAttribute() for PDO::MYSQL_ATTR_READ_DEFAULT_FILE +Failed to getAttribute() for Pdo\Mysql::ATTR_INIT_COMMAND +Failed to getAttribute() for Pdo\Mysql::ATTR_READ_DEFAULT_FILE +Failed to getAttribute() for Pdo\Mysql::ATTR_READ_DEFAULT_GROUP +Failed to getAttribute() for Pdo\Mysql::ATTR_READ_DEFAULT_FILE +Failed to getAttribute() for Pdo\Mysql::ATTR_READ_DEFAULT_FILE done! diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt index ec6bce78b7c41..d86f9b3d8773d 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt @@ -63,5 +63,8 @@ MySQLPDOTest::skip(); print "done!"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Looking up the DSN from a URI is deprecated due to possible security concerns with DSNs coming from remote URIs in %s on line %d + +Deprecated: Looking up the DSN from a URI is deprecated due to possible security concerns with DSNs coming from remote URIs in %s on line %d done! diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_init_command.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_init_command.phpt index 94db61e00ded4..b9562247af863 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_init_command.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_init_command.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO::MYSQL_ATTR_INIT_COMMAND +Pdo\Mysql::ATTR_INIT_COMMAND --EXTENSIONS-- pdo_mysql --SKIPIF-- @@ -22,7 +22,7 @@ error_reporting=E_ALL $create = sprintf('CREATE TABLE %s(id INT)', $table); var_dump($create); - $db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => $create)); + $db = new PDO($dsn, $user, $pass, array(Pdo\Mysql::ATTR_INIT_COMMAND => $create)); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); $info = $db->errorInfo(); diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_max_buffer_size.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_max_buffer_size.phpt index 293eb71ca0a02..00a0eb0edc105 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_max_buffer_size.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_max_buffer_size.phpt @@ -1,5 +1,5 @@ --TEST-- -MySQL PDO->__construct(), PDO::MYSQL_ATTR_MAX_BUFFER_SIZE +MySQL PDO->__construct(), Pdo\Mysql::ATTR_MAX_BUFFER_SIZE --EXTENSIONS-- pdo_mysql --SKIPIF-- @@ -7,7 +7,7 @@ pdo_mysql require_once __DIR__ . '/inc/mysql_pdo_test.inc'; MySQLPDOTest::skip(); if (MySQLPDOTest::isPDOMySQLnd()) - die("skip PDO::MYSQL_ATTR_MAX_BUFFER_SIZE not supported with mysqlnd"); + die("skip Pdo\Mysql::ATTR_MAX_BUFFER_SIZE not supported with mysqlnd"); ?> --FILE-- $buffer_size, + Pdo\Mysql::ATTR_MAX_BUFFER_SIZE => $buffer_size, /* buffer is only relevant with native PS */ - PDO::MYSQL_ATTR_DIRECT_QUERY => 0, + Pdo\Mysql::ATTR_DIRECT_QUERY => 0, PDO::ATTR_EMULATE_PREPARES => 0, ]); diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt index 7d0256500f555..16f19da7d1b05 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO::MYSQL_ATTR_MULTI_STATEMENTS +Pdo\Mysql::ATTR_MULTI_STATEMENTS --EXTENSIONS-- pdo_mysql --SKIPIF-- @@ -37,7 +37,7 @@ error_reporting=E_ALL var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // New connection, does not allow multiple statements. - $db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => false)); + $db = new PDO($dsn, $user, $pass, array(Pdo\Mysql::ATTR_MULTI_STATEMENTS => false)); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); $stmt = $db->query(sprintf('SELECT * FROM %s; INSERT INTO %s(id) VALUES (3)', $table, $table)); diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt index f308f3384f854..d116aa701a142 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt @@ -47,7 +47,7 @@ MySQLPDOTest::skip(); $have_procedures = false; $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); if ($have_procedures && (false !== $db->exec("DROP PROCEDURE IF EXISTS {$procedure}")) && (false !== $db->exec("CREATE PROCEDURE {$procedure}() BEGIN SELECT NULL as z, '' AS a, ' ' AS b, TRIM(' ') as c, ' d' AS d, ' e' AS e; END;"))) { diff --git a/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt b/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt index 9876ae0759f33..066843fa71f65 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_exec_load_data.phpt @@ -55,7 +55,7 @@ function exec_and_count($offset, &$db, $sql, $exp) { } require_once __DIR__ . '/inc/mysql_pdo_test.inc'; -$db = MySQLPDOTest::factoryWithAttr([PDO::MYSQL_ATTR_LOCAL_INFILE=>true]); +$db = MySQLPDOTest::factoryWithAttr([Pdo\Mysql::ATTR_LOCAL_INFILE=>true]); /* affected rows related */ diff --git a/ext/pdo_mysql/tests/pdo_mysql_exec_select.phpt b/ext/pdo_mysql/tests/pdo_mysql_exec_select.phpt index fe1550776dc55..fc52a20f21720 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_exec_select.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_exec_select.phpt @@ -38,7 +38,7 @@ MySQLPDOTest::skip(); exec_and_count(4, $db, "INSERT INTO test_mysql_exec_select(id, col1) VALUES (1, 'a')", 1); // question is: will the result set be cleaned up, will it be possible to run more queries on the line? // buffered or unbuffered does not matter! - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); exec_and_count(5, $db, 'SELECT id FROM test_mysql_exec_select', 0); exec_and_count(6, $db, "INSERT INTO test_mysql_exec_select(id, col1) VALUES (2, 'b')", 1); @@ -57,6 +57,6 @@ $db = MySQLPDOTest::factory(); $db->query('DROP TABLE IF EXISTS test_mysql_exec_select'); ?> --EXPECTF-- -Warning: PDO::exec(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d -[006] Expecting '1'/integer got ''/boolean when running 'INSERT INTO test_mysql_exec_select(id, col1) VALUES (2, 'b')', [HY000] HY000 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. +Warning: PDO::exec(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d +[006] Expecting '1'/integer got ''/boolean when running 'INSERT INTO test_mysql_exec_select(id, col1) VALUES (2, 'b')', [HY000] HY000 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. done! diff --git a/ext/pdo_mysql/tests/pdo_mysql_get_attribute.phpt b/ext/pdo_mysql/tests/pdo_mysql_get_attribute.phpt index 6e83be8e1a8f9..ba4aeb7051ef4 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_get_attribute.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_get_attribute.phpt @@ -50,27 +50,27 @@ MySQLPDOTest::skipNotTransactionalEngine(); $obj = new stdClass(); set_and_get(4, $db, PDO::ATTR_AUTOCOMMIT, $obj); - set_and_get(5, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, 1); - set_and_get(6, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, 0); - set_and_get(7, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, -1); + set_and_get(5, $db, Pdo\Mysql::ATTR_LOCAL_INFILE, 1); + set_and_get(6, $db, Pdo\Mysql::ATTR_LOCAL_INFILE, 0); + set_and_get(7, $db, Pdo\Mysql::ATTR_LOCAL_INFILE, -1); $tmp = array(); - set_and_get(8, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, $tmp); + set_and_get(8, $db, Pdo\Mysql::ATTR_LOCAL_INFILE, $tmp); - set_and_get(9, $db, PPDO::MYSQL_ATTR_INIT_COMMAND, ''); - set_and_get(10, $db, PPDO::MYSQL_ATTR_INIT_COMMAND, 'SOME SQL'); - set_and_get(11, $db, PPDO::MYSQL_ATTR_INIT_COMMAND, -1); + set_and_get(9, $db, PPdo\Mysql::ATTR_INIT_COMMAND, ''); + set_and_get(10, $db, PPdo\Mysql::ATTR_INIT_COMMAND, 'SOME SQL'); + set_and_get(11, $db, PPdo\Mysql::ATTR_INIT_COMMAND, -1); */ /* - PDO::MYSQL_ATTR_READ_DEFAULT_FILE (integer) + Pdo\Mysql::ATTR_READ_DEFAULT_FILE (integer) Read options from the named option file instead of from my.cnf. - PDO::MYSQL_ATTR_READ_DEFAULT_GROUP (integer) + Pdo\Mysql::ATTR_READ_DEFAULT_GROUP (integer) Read options from the named group from my.cnf or the file specified with MYSQL_READ_DEFAULT_FILE. - PDO::MYSQL_ATTR_MAX_BUFFER_SIZE (integer) + Pdo\Mysql::ATTR_MAX_BUFFER_SIZE (integer) Maximum buffer size. Defaults to 1 MiB. - PDO::MYSQL_ATTR_DIRECT_QUERY (integer) + Pdo\Mysql::ATTR_DIRECT_QUERY (integer) Perform direct queries, don't use prepared statements. */ diff --git a/ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt b/ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt index 91a67260f0397..af065bd7d9075 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_local_infile_default_off.phpt @@ -6,7 +6,7 @@ pdo_mysql @@ -19,8 +19,8 @@ $user = PDO_MYSQL_TEST_USER; $pass = PDO_MYSQL_TEST_PASS; $db = new PDO($dsn, $user, $pass); -echo var_export($db->getAttribute(PDO::MYSQL_ATTR_LOCAL_INFILE)), "\n"; -echo var_export($db->getAttribute(PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY)), "\n"; +echo var_export($db->getAttribute(Pdo\Mysql::ATTR_LOCAL_INFILE)), "\n"; +echo var_export($db->getAttribute(Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY)), "\n"; echo "done!\n"; ?> --EXPECT-- diff --git a/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_allowed.phpt b/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_allowed.phpt index 2b7f4673ddaf3..7c910e2ba80c6 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_allowed.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_allowed.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY vs access allowed +Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY vs access allowed --EXTENSIONS-- pdo_mysql --SKIPIF-- @@ -7,7 +7,7 @@ pdo_mysql require_once __DIR__ . '/inc/mysql_pdo_test.inc'; MySQLPDOTest::skip(); MySQLPDOTest::skipInfileNotAllowed(); -if (!defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) { +if (!defined('Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY')) { die("skip No MYSQL_ATTR_LOCAL_INFILE_DIRECTORY support"); } ?> @@ -33,8 +33,8 @@ if (!defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) { require_once __DIR__ . '/inc/mysql_pdo_test.inc'; $db = MySQLPDOTest::factoryWithAttr([ - PDO::MYSQL_ATTR_LOCAL_INFILE=>false, - PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY=>__DIR__."/foo", + Pdo\Mysql::ATTR_LOCAL_INFILE=>false, + Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY=>__DIR__."/foo", ]); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_denied.phpt b/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_denied.phpt index ccf2abd4a86d9..58bac57748eaa 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_denied.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_local_infile_directory_denied.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY vs access denied +Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY vs access denied --EXTENSIONS-- pdo_mysql --SKIPIF-- @@ -7,7 +7,7 @@ pdo_mysql require_once __DIR__ . '/inc/mysql_pdo_test.inc'; MySQLPDOTest::skip(); MySQLPDOTest::skipInfileNotAllowed(); -if (!defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) { +if (!defined('Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY')) { die("skip No MYSQL_ATTR_LOCAL_INFILE_DIRECTORY support"); } ?> @@ -33,8 +33,8 @@ if (!defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) { require_once __DIR__ . '/inc/mysql_pdo_test.inc'; $db = MySQLPDOTest::factoryWithAttr([ - PDO::MYSQL_ATTR_LOCAL_INFILE=>false, - PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY=>__DIR__."/foo/bar", + Pdo\Mysql::ATTR_LOCAL_INFILE=>false, + Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY=>__DIR__."/foo/bar", ]); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_local_infile_overrides_local_infile_directory.phpt b/ext/pdo_mysql/tests/pdo_mysql_local_infile_overrides_local_infile_directory.phpt index b99375c37b6ee..d454694ef2c30 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_local_infile_overrides_local_infile_directory.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_local_infile_overrides_local_infile_directory.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO::MYSQL_ATTR_LOCAL_INFILE overrides PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY +Pdo\Mysql::ATTR_LOCAL_INFILE overrides Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY --EXTENSIONS-- pdo_mysql --SKIPIF-- @@ -7,7 +7,7 @@ pdo_mysql require_once __DIR__ . '/inc/mysql_pdo_test.inc'; MySQLPDOTest::skip(); MySQLPDOTest::skipInfileNotAllowed(); -if (!defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) { +if (!defined('Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY')) { die("skip No MYSQL_ATTR_LOCAL_INFILE_DIRECTORY support"); } ?> @@ -33,8 +33,8 @@ if (!defined('PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY')) { require_once __DIR__ . '/inc/mysql_pdo_test.inc'; $db = MySQLPDOTest::factoryWithAttr([ - PDO::MYSQL_ATTR_LOCAL_INFILE=>true, - PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY=>__DIR__."/foo/bar", + Pdo\Mysql::ATTR_LOCAL_INFILE=>true, + Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY=>__DIR__."/foo/bar", ]); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt b/ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt index cbdbc063dd8a1..e5176b44f158b 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_local_infile_set_on.phpt @@ -15,8 +15,8 @@ $dsn = MySQLPDOTest::getDSN(); $user = PDO_MYSQL_TEST_USER; $pass = PDO_MYSQL_TEST_PASS; -$db = new PDO($dsn, $user, $pass, [PDO::MYSQL_ATTR_LOCAL_INFILE => true]); -echo var_export($db->getAttribute(PDO::MYSQL_ATTR_LOCAL_INFILE)), "\n"; +$db = new PDO($dsn, $user, $pass, [Pdo\Mysql::ATTR_LOCAL_INFILE => true]); +echo var_export($db->getAttribute(Pdo\Mysql::ATTR_LOCAL_INFILE)), "\n"; echo "done!\n"; ?> --EXPECT-- diff --git a/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt b/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt index b699dbdaa5719..75abb0ca39d5f 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt @@ -1,5 +1,5 @@ --TEST-- -MySQL PDOStatement->nextRowSet() with PDO::MYSQL_ATTR_MULTI_STATEMENTS either true or false +MySQL PDOStatement->nextRowSet() with Pdo\Mysql::ATTR_MULTI_STATEMENTS either true or false --EXTENSIONS-- pdo_mysql --SKIPIF-- @@ -35,21 +35,21 @@ MySQLPDOTest::skip(); printf("Native PS...\n"); foreach (array(false, true) as $multi) { $value = $multi ? 'true' : 'false'; - echo "\nTesting with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to {$value}\n"; + echo "\nTesting with Pdo\Mysql::ATTR_MULTI_STATEMENTS set to {$value}\n"; $dsn = MySQLPDOTest::getDSN(); $user = PDO_MYSQL_TEST_USER; $pass = PDO_MYSQL_TEST_PASS; - $db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => $multi)); + $db = new PDO($dsn, $user, $pass, array(Pdo\Mysql::ATTR_MULTI_STATEMENTS => $multi)); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 1); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); test_proc($db); - $db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => $multi)); + $db = new PDO($dsn, $user, $pass, array(Pdo\Mysql::ATTR_MULTI_STATEMENTS => $multi)); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 0); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); test_proc($db); @@ -81,7 +81,7 @@ $db->exec('DROP PROCEDURE IF EXISTS pdo_mysql_multi_stmt_nextrowset_p'); --EXPECTF-- Native PS... -Testing with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to false +Testing with Pdo\Mysql::ATTR_MULTI_STATEMENTS set to false array(3) { [0]=> array(1) { @@ -172,7 +172,7 @@ bool(false) Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'INSERT INTO pdo_mysql_multi_stmt_nextrowset (id, label) VALUES (99, 'x')' at line 1 in %s on line %d string(5) "42000" -Testing with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to true +Testing with Pdo\Mysql::ATTR_MULTI_STATEMENTS set to true array(3) { [0]=> array(1) { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt index 29074fb5505f5..e8ff3781b350b 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated.phpt @@ -82,8 +82,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous.phpt index f16f9078758ff..f8196bcd61add 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous.phpt @@ -13,8 +13,8 @@ MySQLPDOTest::skip(); $db = MySQLPDOTest::factory(); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); $db->exec(sprintf('CREATE TABLE test_prepare_emulated_anonymous(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); @@ -33,8 +33,8 @@ MySQLPDOTest::skip(); // now the same with native PS printf("now the same with native PS\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to switch off emulated prepared statements, test will fail\n"); $db->exec('DELETE FROM test_prepare_emulated_anonymous'); diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous_placeholders.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous_placeholders.phpt index ac4f85949bb17..409d9b1f86c0a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous_placeholders.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_anonymous_placeholders.phpt @@ -83,8 +83,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam.phpt index 8406be4db6d76..fdc82d5ab34bc 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam.phpt @@ -82,8 +82,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam_index.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam_index.phpt index 1acc055e12a0c..a94014a183a55 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam_index.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_myisam_index.phpt @@ -85,8 +85,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_placeholder_everywhere.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_placeholder_everywhere.phpt index 92f14a5b2e9bb..3b356cad3dfc8 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_placeholder_everywhere.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_emulated_placeholder_everywhere.phpt @@ -15,8 +15,8 @@ MySQLPDOTest::skip(); try { // native PS - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to switch off emulated prepared statements, test will fail\n"); $db->exec(sprintf('CREATE TABLE test_prepare_emulated_placeholder_everywhere(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); @@ -35,8 +35,8 @@ MySQLPDOTest::skip(); // now the same with emulated PS printf("now the same with emulated PS\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to switch on emulated prepared statements, test will fail\n"); $stmt = $db->prepare('SELECT ? FROM test_prepare_emulated_placeholder_everywhere WHERE ? > ?'); diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt index 02690d4164c69..7db84207f19cc 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native.phpt @@ -91,8 +91,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_anonymous_placeholder.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_anonymous_placeholder.phpt index db7844b1e6fbf..2ac60de4ae624 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_anonymous_placeholder.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_anonymous_placeholder.phpt @@ -91,8 +91,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt index 5d40bc826233f..68cfa4203cfe7 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_clear_error.phpt @@ -17,8 +17,8 @@ MySQLPDOTest::skip(); $db->exec(sprintf('CREATE TABLE test_prepare_native_clear_error(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); // We need to run the emulated version first. Native version will cause a fatal error - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); // INSERT a single row @@ -40,8 +40,8 @@ MySQLPDOTest::skip(); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // Native PS - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[005] Unable to turn off emulated prepared statements\n"); $stmt = $db->prepare('SELECT unknown_column FROM test_prepare_native_clear_error WHERE id > :placeholder ORDER BY id ASC'); diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_column.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_column.phpt index 5786b009500aa..ec63d4a4b7501 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_column.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_column.phpt @@ -15,8 +15,8 @@ MySQLPDOTest::skip(); $table = 'pdo_mysql_prepare_native_column'; MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); $stmt = $db->prepare("SELECT :param FROM {$table} ORDER BY id ASC LIMIT 1"); diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_dup_named_placeholder.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_dup_named_placeholder.phpt index 21bbe8728ed8b..ef38604c449b6 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_dup_named_placeholder.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_dup_named_placeholder.phpt @@ -16,8 +16,8 @@ MySQLPDOTest::skip(); try { $db->exec(sprintf('CREATE TABLE test_prepare_native_dup_named(id INT, label1 CHAR(255), label2 CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); printf("Native...\n"); @@ -36,8 +36,8 @@ MySQLPDOTest::skip(); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // Now the same with emulated PS. - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to turn on emulated prepared statements\n"); printf("Emulated...\n"); @@ -72,8 +72,8 @@ MySQLPDOTest::skip(); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // native... - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[007] Unable to turn off emulated prepared statements\n"); printf("Native...\n"); diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt index 9e5607fa4cefd..adca8ecfc233d 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_mixed_style.phpt @@ -15,8 +15,8 @@ MySQLPDOTest::skip(); $table = 'pdo_mysql_prepare_native_mixed_style'; MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); $stmt = $db->query("DELETE FROM {$table}"); diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam.phpt index c8ede104016a3..c4a4f7c6f3832 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam.phpt @@ -91,8 +91,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam_index.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam_index.phpt index f1547281438ec..e84dd18b957c2 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam_index.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_myisam_index.phpt @@ -91,8 +91,8 @@ MySQLPDOTest::skip(); } try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); try { diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_named_placeholder.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_named_placeholder.phpt index 2e23def163345..93bedbe9de74a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_named_placeholder.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_named_placeholder.phpt @@ -16,8 +16,8 @@ MySQLPDOTest::skip(); $db->exec(sprintf('CREATE TABLE test_prepare_native_named_placeholder(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); // INSERT a single row @@ -39,8 +39,8 @@ MySQLPDOTest::skip(); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); // Now the same with emulated PS. - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to turn on emulated prepared statements\n"); // Note that the "named placeholder" is enclosed by double quotes. diff --git a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_placeholder_everywhere.phpt b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_placeholder_everywhere.phpt index 575af4a8f2c8f..4afccdc9e2987 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_prepare_native_placeholder_everywhere.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_prepare_native_placeholder_everywhere.phpt @@ -14,8 +14,8 @@ MySQLPDOTest::skip(); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to switch on emulated prepared statements, test will fail\n"); $db->exec(sprintf('CREATE TABLE test_prepare_native_named_placeholder_everywhere(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); @@ -31,8 +31,8 @@ MySQLPDOTest::skip(); // now the same with native PS printf("now the same with native PS\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to switch off emulated prepared statements, test_prepare_native_named_placeholder_everywhere will fail\n"); $stmt = $db->prepare('SELECT ?, id, label FROM test_prepare_native_named_placeholder_everywhere WHERE ? = ? ORDER BY id ASC'); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindcolumn.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindcolumn.phpt index cce3dc9393a37..8f144b611df76 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindcolumn.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindcolumn.phpt @@ -16,8 +16,8 @@ MySQLPDOTest::skip(); MySQLPDOTest::createTestTable($table, $db); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); $stmt = $db->prepare("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2"); @@ -56,8 +56,8 @@ MySQLPDOTest::skip(); $index++; } - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[007] Unable to turn off emulated prepared statements\n"); $stmt = $db->prepare("SELECT id, label FROM {$table} ORDER BY id ASC LIMIT 2, 2"); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam.phpt index b0bbad59d8e92..92e6f446e1b36 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam.phpt @@ -84,32 +84,32 @@ MySQLPDOTest::skip(); try { printf("Emulated PS...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); printf("Buffered...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); pdo_mysql_stmt_bindparam($db, 3); printf("Unbuffered...\n"); MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); pdo_mysql_stmt_bindparam($db, 4); printf("Native PS...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to turn off emulated prepared statements\n"); printf("Buffered...\n"); MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); pdo_mysql_stmt_bindparam($db, 5); printf("Unbuffered...\n"); MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); pdo_mysql_stmt_bindparam($db, 6); } catch (PDOException $e) { diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam_types.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam_types.phpt index b315c97b91203..fde08dfa6932a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam_types.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindparam_types.phpt @@ -14,9 +14,9 @@ MySQLPDOTest::skip(); function pdo_mysql_stmt_bindparam_types_do($db, $offset, $native, $sql_type, $value) { if ($native) - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); else - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); $sql = sprintf('CREATE TABLE test_stmt_bindparam_types(id INT, label %s) ENGINE=%s', $sql_type, MySQLPDOTest::getTableEngine()); if ((!$stmt = $db->prepare($sql)) || (!$stmt->execute())) diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindvalue.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindvalue.phpt index c558eb6f81dad..7d214e0c7e239 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_bindvalue.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_bindvalue.phpt @@ -17,8 +17,8 @@ MySQLPDOTest::skip(); printf("Testing native PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); printf("Binding variable...\n"); @@ -157,8 +157,8 @@ MySQLPDOTest::skip(); printf("Testing emulated PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); printf("Binding variable...\n"); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor.phpt index af052a02423ff..65dfbb660bc3a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor.phpt @@ -21,7 +21,7 @@ MySQLPDOTest::skip(); // This one should fail. I let it fail to prove that closeCursor() makes a difference. // If no error messages gets printed do not know if proper usage of closeCursor() makes any // difference or not. That's why we need to cause an error here. - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); $stmt1 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); // query() shall fail! $stmt2 = $db->query("SELECT id, label FROM {$table} ORDER BY id ASC"); @@ -46,7 +46,7 @@ MySQLPDOTest::skip(); $stmt2->execute(); $stmt2->closeCursor(); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); // check if changing the fetch mode from unbuffered to buffered will // cause any harm to a statement created prior to the change $stmt1->execute(); @@ -110,33 +110,33 @@ MySQLPDOTest::skip(); try { printf("Testing emulated PS...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); printf("Buffered...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); MySQLPDOTest::createTestTable($table, $db); pdo_mysql_stmt_closecursor($db); printf("Unbuffered...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); MySQLPDOTest::createTestTable($table, $db); pdo_mysql_stmt_closecursor($db); printf("Testing native PS...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); printf("Buffered...\n"); MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); pdo_mysql_stmt_closecursor($db); printf("Unbuffered...\n"); MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); pdo_mysql_stmt_closecursor($db); } catch (PDOException $e) { @@ -156,23 +156,23 @@ $db->exec('DROP TABLE IF EXISTS pdo_mysql_stmt_closecursor'); Testing emulated PS... Buffered... -Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d +Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d in = 0 -> id = 1 (integer) / label = 'a' (string) in = 0 -> id = 2 (integer) / label = 'b' (string) Unbuffered... -Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d +Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d in = 0 -> id = 1 (integer) / label = 'a' (string) in = 0 -> id = 2 (integer) / label = 'b' (string) Testing native PS... Buffered... -Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d +Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d in = 0 -> id = 1 (integer) / label = 'a' (string) in = 0 -> id = 2 (integer) / label = 'b' (string) Unbuffered... -Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d +Warning: PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the Pdo\Mysql::ATTR_USE_BUFFERED_QUERY attribute. in %s on line %d in = 0 -> id = 1 (integer) / label = 'a' (string) in = 0 -> id = 2 (integer) / label = 'b' (string) done! diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor_empty.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor_empty.phpt index 33127f4ee242f..b0880f3548985 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor_empty.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_closecursor_empty.phpt @@ -16,11 +16,11 @@ MySQLPDOTest::skip(); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); MySQLPDOTest::createTestTable($table, $db); $stmt = $db->prepare("SELECT id, label FROM {$table} WHERE id > ? ORDER BY id ASC LIMIT 2"); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_columncount.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_columncount.phpt index b55725057e234..81d2bd6386e3a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_columncount.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_columncount.phpt @@ -20,8 +20,8 @@ MySQLPDOTest::skip(); // Internal data structures should be the same in both cases. printf("Testing emulated PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); $stmt = $db->prepare("SELECT id, label, '?' as foo FROM {$table}"); @@ -38,8 +38,8 @@ MySQLPDOTest::skip(); printf("Testing native PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to turn off emulated prepared statements\n"); $stmt = $db->prepare("SELECT id, label, '?' as foo, 'TODO - Stored Procedure' as bar FROM {$table}"); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt index de4cb8b97bfb6..8602fa7b36008 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_errorcode.phpt @@ -16,8 +16,8 @@ MySQLPDOTest::skip(); printf("Testing emulated PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); $stmt = $db->prepare('SELECT id FROM pdo_mysql_stmt_errorcode_ihopeitdoesnotexist ORDER BY id ASC'); @@ -32,8 +32,8 @@ MySQLPDOTest::skip(); printf("Testing native PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to turn off emulated prepared statements\n"); $stmt = $db->prepare('SELECT id FROM pdo_mysql_stmt_errorcode_ihopeitdoesnotexist ORDER BY id ASC'); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_errorinfo.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_errorinfo.phpt index 6b2a9281d9c21..04fb7d802e62b 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_errorinfo.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_errorinfo.phpt @@ -17,8 +17,8 @@ MySQLPDOTest::skip(); printf("Testing emulated PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); $stmt = $db->prepare('SELECT id FROM pdo_mysql_stmt_errorinfo_ihopeitdoesnotexist ORDER BY id ASC'); @@ -40,8 +40,8 @@ MySQLPDOTest::skip(); printf("Testing native PS...\n"); try { - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to turn off emulated prepared statements\n"); $stmt = $db->prepare('SELECT id FROM pdo_mysql_stmt_errorinfo_ihopeitdoesnotexist ORDER BY id ASC'); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_class.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_class.phpt index 4d5db44ea91b4..4ba394cc7cd34 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_class.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_class.phpt @@ -75,8 +75,8 @@ MySQLPDOTest::skip(); } - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); $db->exec(sprintf('CREATE TABLE test_stmt_fetch_class(id INT, myobj BLOB) ENGINE=%s', @@ -110,6 +110,10 @@ $db = MySQLPDOTest::factory(); $db->exec('DROP TABLE IF EXISTS test_stmt_fetch_class'); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d Creating an object, serializing it and writing it to DB... myclass::singleton(Creating object) diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_non_select.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_non_select.phpt index 0027d1ea52ff9..421276c570d7f 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_non_select.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_non_select.phpt @@ -18,8 +18,8 @@ MySQLPDOTest::skip(); try { // Emulated PS first - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); - if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn on emulated prepared statements\n"); if (!is_object($stmt = $db->query("DESCRIBE {$table} id"))) @@ -68,8 +68,8 @@ MySQLPDOTest::skip(); printf("[010] Emulated PS, EXPLAIN returned no results\n"); // And now native PS - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[011] Unable to turn off emulated prepared statements\n"); $native_support = 'no'; diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize.phpt index 8aaf65f52d9ea..455b04b4cb071 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize.phpt @@ -75,8 +75,8 @@ MySQLPDOTest::skip(); } - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); $db->exec(sprintf('CREATE TABLE test_stmt_fetch_serialize(id INT, myobj BLOB) ENGINE=%s', @@ -107,6 +107,10 @@ $db = MySQLPDOTest::factory(); $db->exec('DROP TABLE IF EXISTS test_stmt_fetch_serialize'); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d Creating an object, serializing it and writing it to DB... myclass::singleton(Creating object) diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize_fetch_class.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize_fetch_class.phpt index f2f6c89ad3897..175f2c69e26e0 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize_fetch_class.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_fetch_serialize_fetch_class.phpt @@ -75,8 +75,8 @@ MySQLPDOTest::skip(); } - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[002] Unable to turn off emulated prepared statements\n"); $db->exec(sprintf('CREATE TABLE test_stmt_fetchserialize_fetch_class(id INT, myobj BLOB) ENGINE=%s', @@ -110,6 +110,10 @@ $db = MySQLPDOTest::factory(); $db->exec('DROP TABLE IF EXISTS test_stmt_fetchserialize_fetch_class'); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d Creating an object, serializing it and writing it to DB... myclass::singleton(Creating object) diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt index 0552a87aa42d9..9b09491e0cbf7 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_getcolumnmeta.phpt @@ -37,8 +37,8 @@ try { $emulated = $stmt->getColumnMeta(0); printf("Testing native PS...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[007] Unable to turn off emulated prepared statements\n"); $stmt = $db->prepare('SELECT id FROM test_stmt_getcolumnmeta ORDER BY id ASC'); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_nextrowset.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_nextrowset.phpt index df2d3b402d83d..0415a04fdab6f 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_nextrowset.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_nextrowset.phpt @@ -63,14 +63,14 @@ MySQLPDOTest::skipNotMySQLnd(); printf("Emulated PS...\n"); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 1); test_proc1($db); test_proc2($db); $db = MySQLPDOTest::factory(); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 0); test_proc1($db); test_proc2($db); @@ -78,14 +78,14 @@ MySQLPDOTest::skipNotMySQLnd(); printf("Native PS...\n"); $db = MySQLPDOTest::factory(); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 1); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); test_proc1($db); test_proc2($db); $db = MySQLPDOTest::factory(); $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 0); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); test_proc1($db); diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_unbuffered_2050.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_unbuffered_2050.phpt index aca3e6a084cbd..fcba9e44e694c 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_unbuffered_2050.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_unbuffered_2050.phpt @@ -18,13 +18,13 @@ if (MYSQLPDOTest::isPDOMySQLnd()) try { printf("Native PS...\n"); - $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); - if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + $db->setAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(Pdo\Mysql::ATTR_DIRECT_QUERY)) printf("[004] Unable to turn off emulated prepared statements\n"); printf("Buffered...\n"); MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, true); $stmt = $db->query("SELECT id, label FROM {$table} WHERE id = 1"); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); $stmt = $db->query("SELECT id, label FROM {$table} WHERE id = 1"); @@ -32,7 +32,7 @@ if (MYSQLPDOTest::isPDOMySQLnd()) printf("Unbuffered...\n"); MySQLPDOTest::createTestTable($table, $db); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, false); $stmt = $db->query("SELECT id, label FROM {$table} WHERE id = 1"); var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); /* diff --git a/ext/pdo_mysql/tests/pdo_mysql_stmt_variable_columncount.phpt b/ext/pdo_mysql/tests/pdo_mysql_stmt_variable_columncount.phpt index fb35381769744..48353f4cbdb3c 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_stmt_variable_columncount.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_stmt_variable_columncount.phpt @@ -57,7 +57,7 @@ MySQLPDOTest::skip(); // Libmysql cannot handle such a stored procedure. You will see leaks with libmysql $db = MySQLPDOTest::factory(); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 1); $stmt = $db->prepare("CALL {$procedure}(?)"); $stmt->bindParam(1, $columns); for ($i = 5; $i < 10; $i++) { @@ -88,7 +88,7 @@ MySQLPDOTest::skip(); // Libmysql cannot handle such a stored procedure. You will see leaks with libmysql $db = MySQLPDOTest::factory(); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); - $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->setAttribute(Pdo\Mysql::ATTR_USE_BUFFERED_QUERY, 1); $db->exec('SET @numcols = 1'); $stmt = $db->prepare("CALL {$procedure}()"); $stmt->execute(); diff --git a/ext/pdo_mysql/tests/pdo_mysql_types.phpt b/ext/pdo_mysql/tests/pdo_mysql_types.phpt index 462a542c24c17..7c7926a8cb9f2 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_types.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_types.phpt @@ -105,7 +105,7 @@ MySQLPDOTest::skip(); test_type($db, 90, 'MEDIUMINT UNSIGNED', 16777215, ($is_mysqlnd) ? 16777215 : '16777215'); test_type($db, 100, 'INT', -2147483648, - ($is_mysqlnd) ? ((PHP_INT_SIZE > 4) ? (int)-2147483648 : (double)-2147483648) : '-2147483648', + ($is_mysqlnd) ? ((PHP_INT_SIZE > 4) ? (int)-2147483648 : (float)-2147483648) : '-2147483648', NULL, ($is_mysqlnd) ? 'integer' : NULL); test_type($db, 110, 'INT UNSIGNED', 4294967295, ($is_mysqlnd) ? ((PHP_INT_SIZE > 4) ? 4294967295 : '4294967295') : '4294967295'); diff --git a/ext/pdo_mysql/tests/php_8.5_deprecations.phpt b/ext/pdo_mysql/tests/php_8.5_deprecations.phpt new file mode 100644 index 0000000000000..4d163c2f48cdc --- /dev/null +++ b/ext/pdo_mysql/tests/php_8.5_deprecations.phpt @@ -0,0 +1,81 @@ +--TEST-- +PDO_mysql: PHP 8.5 deprecations +--EXTENSIONS-- +pdo_mysql +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Deprecated: Constant PDO::MYSQL_ATTR_USE_BUFFERED_QUERY is deprecated since 8.5, use Pdo\Mysql::ATTR_USE_BUFFERED_QUERY instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_LOCAL_INFILE is deprecated since 8.5, use Pdo\Mysql::ATTR_LOCAL_INFILE instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY is deprecated since 8.5, use Pdo\Mysql::ATTR_LOCAL_INFILE_DIRECTORY instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_INIT_COMMAND is deprecated since 8.5, use Pdo\Mysql::ATTR_INIT_COMMAND instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_COMPRESS is deprecated since 8.5, use Pdo\Mysql::ATTR_COMPRESS instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_DIRECT_QUERY is deprecated since 8.5, use Pdo\Mysql::ATTR_DIRECT_QUERY instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_FOUND_ROWS is deprecated since 8.5, use Pdo\Mysql::ATTR_FOUND_ROWS instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_IGNORE_SPACE is deprecated since 8.5, use Pdo\Mysql::ATTR_IGNORE_SPACE instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_SSL_KEY is deprecated since 8.5, use Pdo\Mysql::ATTR_SSL_KEY instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_SSL_CERT is deprecated since 8.5, use Pdo\Mysql::ATTR_SSL_CERT instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_SSL_CA is deprecated since 8.5, use Pdo\Mysql::ATTR_SSL_CA instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_SSL_CAPATH is deprecated since 8.5, use Pdo\Mysql::ATTR_SSL_CAPATH instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_SSL_CIPHER is deprecated since 8.5, use Pdo\Mysql::ATTR_SSL_CIPHER instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT is deprecated since 8.5, use Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY is deprecated since 8.5, use Pdo\Mysql::ATTR_SERVER_PUBLIC_KEY instead in %s on line %d + +Deprecated: Constant PDO::MYSQL_ATTR_MULTI_STATEMENTS is deprecated since 8.5, use Pdo\Mysql::ATTR_MULTI_STATEMENTS instead in %s on line %d +int(1000) +int(1001) +int(1014) +int(1002) +int(1003) +int(20) +int(1004) +int(1005) +int(1006) +int(1007) +int(1008) +int(1009) +int(1010) +int(1013) +int(1011) +int(1012) diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c index 1f5009c746b61..8e27d27173c0b 100644 --- a/ext/pdo_odbc/odbc_stmt.c +++ b/ext/pdo_odbc/odbc_stmt.c @@ -26,6 +26,9 @@ #include "php_pdo_odbc.h" #include "php_pdo_odbc_int.h" +/* Buffer size; bigger columns than this become a "long column" */ +#define LONG_COLUMN_BUFFER_SIZE (ZEND_MM_PAGE_SIZE- ZSTR_MAX_OVERHEAD) + enum pdo_odbc_conv_result { PDO_ODBC_CONV_NOT_REQUIRED, PDO_ODBC_CONV_OK, @@ -615,7 +618,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno) /* tell ODBC to put it straight into our buffer, but only if it * isn't "long" data, and only if we haven't already bound a long * column. */ - if (colsize < 256 && !S->going_long) { + if (colsize < LONG_COLUMN_BUFFER_SIZE && !S->going_long) { S->cols[colno].data = emalloc(colsize+1); S->cols[colno].is_long = 0; @@ -631,7 +634,7 @@ static int odbc_stmt_describe(pdo_stmt_t *stmt, int colno) } else { /* allocate a smaller buffer to keep around for smaller * "long" columns */ - S->cols[colno].data = emalloc(256); + S->cols[colno].data = emalloc(LONG_COLUMN_BUFFER_SIZE); S->going_long = 1; S->cols[colno].is_long = 1; } @@ -657,37 +660,57 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo RETCODE rc; /* fetch it into C->data, which is allocated with a length - * of 256 bytes; if there is more to be had, we then allocate + * of the page size minus zend_string overhead (LONG_COLUMN_BUFFER_SIZE); + * if there is more to be had, we then allocate * bigger buffer for the caller to free */ rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, C->data, - 256, &C->fetched_len); + LONG_COLUMN_BUFFER_SIZE, &C->fetched_len); orig_fetched_len = C->fetched_len; - if (rc == SQL_SUCCESS && C->fetched_len < 256) { + if (rc == SQL_SUCCESS && C->fetched_len < LONG_COLUMN_BUFFER_SIZE) { /* all the data fit into our little buffer; * jump down to the generic bound data case */ goto in_data; } if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) { - /* this is a 'long column' - - read the column in 255 byte blocks until the end of the column is reached, reassembling those blocks - in order into the output buffer; 255 bytes are an optimistic assumption, since the driver may assert - more or less NUL bytes at the end; we cater to that later, if actual length information is available - - this loop has to work whether or not SQLGetData() provides the total column length. - calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read - for that size would be slower except maybe for extremely long columns.*/ - char *buf2 = emalloc(256); - zend_string *str = zend_string_init(C->data, 256, 0); - size_t used = 255; /* not 256; the driver NUL terminated the buffer */ + /* + * This is a long column. + * + * Try to get as much as we can at once. If the + * driver somehow has more for us, get more. We'll + * assemble it into one big buffer at the end. + * + * N.B. with n and n+1 mentioned in the comments: + * n is the size returned without null terminator. + * + * The extension previously tried getting it in 256 + * byte blocks, but this could have created trouble + * with some drivers. + * + * However, depending on the driver, fetched_len may + * not contain the number of bytes and SQL_NO_TOTAL + * may be passed. + * The behavior in this case is the same as before, + * dividing the data into blocks. However, it has been + * changed from 256 byte to LONG_COLUMN_BUFFER_SIZE. + */ + ssize_t to_fetch_len; + if (orig_fetched_len == SQL_NO_TOTAL) { + to_fetch_len = C->datalen > (LONG_COLUMN_BUFFER_SIZE - 1) ? (LONG_COLUMN_BUFFER_SIZE - 1) : C->datalen; + } else { + to_fetch_len = orig_fetched_len; + } + ssize_t to_fetch_byte = to_fetch_len + 1; + char *buf2 = emalloc(to_fetch_byte); + zend_string *str = zend_string_init(C->data, to_fetch_byte, 0); + size_t used = to_fetch_len; do { C->fetched_len = 0; - /* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */ - rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, 256, &C->fetched_len); + /* read block. n + 1 bytes => n bytes are actually read, the last 1 is NULL */ + rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, to_fetch_byte, &C->fetched_len); /* adjust `used` in case we have proper length info from the driver */ if (orig_fetched_len >= 0 && C->fetched_len >= 0) { @@ -698,13 +721,13 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, zval *result, enum pdo } /* resize output buffer and reassemble block */ - if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > 255)) { + if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > to_fetch_len)) { /* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx - states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size) - (if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */ - str = zend_string_realloc(str, used + 256, 0); - memcpy(ZSTR_VAL(str) + used, buf2, 256); - used = used + 255; + states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > n (greater than buf2's size) + (if a driver fails to follow that and wrote less than n bytes to buf2, this will AV or read garbage into buf) */ + str = zend_string_realloc(str, used + to_fetch_byte, 0); + memcpy(ZSTR_VAL(str) + used, buf2, to_fetch_byte); + used = used + to_fetch_len; } else if (rc==SQL_SUCCESS) { str = zend_string_realloc(str, used + C->fetched_len, 0); memcpy(ZSTR_VAL(str) + used, buf2, C->fetched_len); diff --git a/ext/pdo_odbc/pdo_odbc.c b/ext/pdo_odbc/pdo_odbc.c index 1052322fe8cfe..1181e314c4d0d 100644 --- a/ext/pdo_odbc/pdo_odbc.c +++ b/ext/pdo_odbc/pdo_odbc.c @@ -61,6 +61,9 @@ zend_ulong pdo_odbc_pool_on = SQL_CP_OFF; zend_ulong pdo_odbc_pool_mode = SQL_CP_ONE_PER_HENV; #endif +#define REGISTER_PDO_ODBC_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \ + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "ODBC_", "Pdo\\Odbc::", value) + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(pdo_odbc) { @@ -101,11 +104,11 @@ PHP_MINIT_FUNCTION(pdo_odbc) register_pdo_odbc_symbols(module_number); - REGISTER_PDO_CLASS_CONST_LONG("ODBC_ATTR_USE_CURSOR_LIBRARY", PDO_ODBC_ATTR_USE_CURSOR_LIBRARY); - REGISTER_PDO_CLASS_CONST_LONG("ODBC_ATTR_ASSUME_UTF8", PDO_ODBC_ATTR_ASSUME_UTF8); - REGISTER_PDO_CLASS_CONST_LONG("ODBC_SQL_USE_IF_NEEDED", SQL_CUR_USE_IF_NEEDED); - REGISTER_PDO_CLASS_CONST_LONG("ODBC_SQL_USE_DRIVER", SQL_CUR_USE_DRIVER); - REGISTER_PDO_CLASS_CONST_LONG("ODBC_SQL_USE_ODBC", SQL_CUR_USE_ODBC); + REGISTER_PDO_ODBC_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_USE_CURSOR_LIBRARY", PDO_ODBC_ATTR_USE_CURSOR_LIBRARY); + REGISTER_PDO_ODBC_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_ASSUME_UTF8", PDO_ODBC_ATTR_ASSUME_UTF8); + REGISTER_PDO_ODBC_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("SQL_USE_IF_NEEDED", SQL_CUR_USE_IF_NEEDED); + REGISTER_PDO_ODBC_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("SQL_USE_DRIVER", SQL_CUR_USE_DRIVER); + REGISTER_PDO_ODBC_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("SQL_USE_ODBC", SQL_CUR_USE_ODBC); pdo_odbc_ce = register_class_Pdo_Odbc(pdo_dbh_ce); pdo_odbc_ce->create_object = pdo_dbh_new; diff --git a/ext/pdo_odbc/tests/bug80783a.phpt b/ext/pdo_odbc/tests/bug80783a.phpt index ab141588e1b4e..d8987cfd0ac3e 100644 --- a/ext/pdo_odbc/tests/bug80783a.phpt +++ b/ext/pdo_odbc/tests/bug80783a.phpt @@ -22,7 +22,7 @@ $string = str_repeat("0123456789", 50); $db->exec("INSERT INTO bug80783a VALUES('$string')"); $stmt = $db->prepare("SELECT name FROM bug80783a"); -$stmt->setAttribute(PDO::ODBC_ATTR_ASSUME_UTF8, true); +$stmt->setAttribute(Pdo\Odbc::ATTR_ASSUME_UTF8, true); $stmt->bindColumn(1, $data, PDO::PARAM_STR); $stmt->execute(); $stmt->fetch(PDO::FETCH_BOUND); diff --git a/ext/pdo_odbc/tests/php_8.5_deprecations.phpt b/ext/pdo_odbc/tests/php_8.5_deprecations.phpt new file mode 100644 index 0000000000000..54be2339f6cf2 --- /dev/null +++ b/ext/pdo_odbc/tests/php_8.5_deprecations.phpt @@ -0,0 +1,31 @@ +--TEST-- +PDO_odbc: PHP 8.5 deprecations +--EXTENSIONS-- +pdo_odbc +--FILE-- + +--EXPECTF-- +Deprecated: Constant PDO::ODBC_ATTR_USE_CURSOR_LIBRARY is deprecated since 8.5, use Pdo\Odbc::ATTR_USE_CURSOR_LIBRARY instead in %s on line %d + +Deprecated: Constant PDO::ODBC_ATTR_ASSUME_UTF8 is deprecated since 8.5, use Pdo\Odbc::ATTR_ASSUME_UTF8 instead in %s on line %d + +Deprecated: Constant PDO::ODBC_SQL_USE_IF_NEEDED is deprecated since 8.5, use Pdo\Odbc::SQL_USE_IF_NEEDED instead in %s on line %d + +Deprecated: Constant PDO::ODBC_SQL_USE_DRIVER is deprecated since 8.5, use Pdo\Odbc::SQL_USE_DRIVER instead in %s on line %d + +Deprecated: Constant PDO::ODBC_SQL_USE_ODBC is deprecated since 8.5, use Pdo\Odbc::SQL_USE_ODBC instead in %s on line %d +int(1000) +int(1001) +int(0) +int(2) +int(1) diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c index 49efa0b238484..e6849aed1195e 100644 --- a/ext/pdo_pgsql/pdo_pgsql.c +++ b/ext/pdo_pgsql/pdo_pgsql.c @@ -175,15 +175,18 @@ PHP_METHOD(Pdo_Pgsql, setNoticeCallback) /* true global environment */ +#define REGISTER_PDO_PGSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \ + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "PGSQL_", "Pdo\\Pgsql::", value) + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(pdo_pgsql) { - REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_PREPARES", PDO_PGSQL_ATTR_DISABLE_PREPARES); - REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_IDLE", (zend_long)PGSQL_TRANSACTION_IDLE); - REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_ACTIVE", (zend_long)PGSQL_TRANSACTION_ACTIVE); - REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INTRANS", (zend_long)PGSQL_TRANSACTION_INTRANS); - REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INERROR", (zend_long)PGSQL_TRANSACTION_INERROR); - REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_UNKNOWN", (zend_long)PGSQL_TRANSACTION_UNKNOWN); + REGISTER_PDO_PGSQL_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_DISABLE_PREPARES", PDO_PGSQL_ATTR_DISABLE_PREPARES); + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_85("PGSQL_TRANSACTION_IDLE", (zend_long)PGSQL_TRANSACTION_IDLE); + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_85("PGSQL_TRANSACTION_ACTIVE", (zend_long)PGSQL_TRANSACTION_ACTIVE); + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_85("PGSQL_TRANSACTION_INTRANS", (zend_long)PGSQL_TRANSACTION_INTRANS); + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_85("PGSQL_TRANSACTION_INERROR", (zend_long)PGSQL_TRANSACTION_INERROR); + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_85("PGSQL_TRANSACTION_UNKNOWN", (zend_long)PGSQL_TRANSACTION_UNKNOWN); PdoPgsql_ce = register_class_Pdo_Pgsql(pdo_dbh_ce); PdoPgsql_ce->create_object = pdo_dbh_new; diff --git a/ext/pdo_pgsql/pdo_pgsql.stub.php b/ext/pdo_pgsql/pdo_pgsql.stub.php index 8e96a55266824..8322b88ca8db8 100644 --- a/ext/pdo_pgsql/pdo_pgsql.stub.php +++ b/ext/pdo_pgsql/pdo_pgsql.stub.php @@ -19,18 +19,23 @@ class Pgsql extends \PDO #endif /** @cvalue PGSQL_TRANSACTION_IDLE */ + #[\Deprecated(since: "8.5", message: "as it has no effect")] public const int TRANSACTION_IDLE = UNKNOWN; /** @cvalue PGSQL_TRANSACTION_ACTIVE */ + #[\Deprecated(since: "8.5", message: "as it has no effect")] public const int TRANSACTION_ACTIVE = UNKNOWN; /** @cvalue PGSQL_TRANSACTION_INTRANS */ + #[\Deprecated(since: "8.5", message: "as it has no effect")] public const int TRANSACTION_INTRANS = UNKNOWN; /** @cvalue PGSQL_TRANSACTION_INERROR */ + #[\Deprecated(since: "8.5", message: "as it has no effect")] public const int TRANSACTION_INERROR = UNKNOWN; /** @cvalue PGSQL_TRANSACTION_UNKNOWN */ + #[\Deprecated(since: "8.5", message: "as it has no effect")] public const int TRANSACTION_UNKNOWN = UNKNOWN; public function escapeIdentifier(string $input): string {} diff --git a/ext/pdo_pgsql/pdo_pgsql_arginfo.h b/ext/pdo_pgsql/pdo_pgsql_arginfo.h index f7f54cb600c72..5cb973a79f5a3 100644 --- a/ext/pdo_pgsql/pdo_pgsql_arginfo.h +++ b/ext/pdo_pgsql/pdo_pgsql_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 225cbb077d441f93b7c6bdb9826ab3e8f634b79d */ + * Stub hash: 0ea21010467d661416f0858f2bda095583ea3a36 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Pdo_Pgsql_escapeIdentifier, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, input, IS_STRING, 0) @@ -105,32 +105,64 @@ static zend_class_entry *register_class_Pdo_Pgsql(zend_class_entry *class_entry_ zval const_TRANSACTION_IDLE_value; ZVAL_LONG(&const_TRANSACTION_IDLE_value, PGSQL_TRANSACTION_IDLE); zend_string *const_TRANSACTION_IDLE_name = zend_string_init_interned("TRANSACTION_IDLE", sizeof("TRANSACTION_IDLE") - 1, 1); - zend_declare_typed_class_constant(class_entry, const_TRANSACTION_IDLE_name, &const_TRANSACTION_IDLE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_class_constant *const_TRANSACTION_IDLE = zend_declare_typed_class_constant(class_entry, const_TRANSACTION_IDLE_name, &const_TRANSACTION_IDLE_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_TRANSACTION_IDLE_name); zval const_TRANSACTION_ACTIVE_value; ZVAL_LONG(&const_TRANSACTION_ACTIVE_value, PGSQL_TRANSACTION_ACTIVE); zend_string *const_TRANSACTION_ACTIVE_name = zend_string_init_interned("TRANSACTION_ACTIVE", sizeof("TRANSACTION_ACTIVE") - 1, 1); - zend_declare_typed_class_constant(class_entry, const_TRANSACTION_ACTIVE_name, &const_TRANSACTION_ACTIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_class_constant *const_TRANSACTION_ACTIVE = zend_declare_typed_class_constant(class_entry, const_TRANSACTION_ACTIVE_name, &const_TRANSACTION_ACTIVE_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_TRANSACTION_ACTIVE_name); zval const_TRANSACTION_INTRANS_value; ZVAL_LONG(&const_TRANSACTION_INTRANS_value, PGSQL_TRANSACTION_INTRANS); zend_string *const_TRANSACTION_INTRANS_name = zend_string_init_interned("TRANSACTION_INTRANS", sizeof("TRANSACTION_INTRANS") - 1, 1); - zend_declare_typed_class_constant(class_entry, const_TRANSACTION_INTRANS_name, &const_TRANSACTION_INTRANS_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_class_constant *const_TRANSACTION_INTRANS = zend_declare_typed_class_constant(class_entry, const_TRANSACTION_INTRANS_name, &const_TRANSACTION_INTRANS_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_TRANSACTION_INTRANS_name); zval const_TRANSACTION_INERROR_value; ZVAL_LONG(&const_TRANSACTION_INERROR_value, PGSQL_TRANSACTION_INERROR); zend_string *const_TRANSACTION_INERROR_name = zend_string_init_interned("TRANSACTION_INERROR", sizeof("TRANSACTION_INERROR") - 1, 1); - zend_declare_typed_class_constant(class_entry, const_TRANSACTION_INERROR_name, &const_TRANSACTION_INERROR_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_class_constant *const_TRANSACTION_INERROR = zend_declare_typed_class_constant(class_entry, const_TRANSACTION_INERROR_name, &const_TRANSACTION_INERROR_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_TRANSACTION_INERROR_name); zval const_TRANSACTION_UNKNOWN_value; ZVAL_LONG(&const_TRANSACTION_UNKNOWN_value, PGSQL_TRANSACTION_UNKNOWN); zend_string *const_TRANSACTION_UNKNOWN_name = zend_string_init_interned("TRANSACTION_UNKNOWN", sizeof("TRANSACTION_UNKNOWN") - 1, 1); - zend_declare_typed_class_constant(class_entry, const_TRANSACTION_UNKNOWN_name, &const_TRANSACTION_UNKNOWN_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_class_constant *const_TRANSACTION_UNKNOWN = zend_declare_typed_class_constant(class_entry, const_TRANSACTION_UNKNOWN_name, &const_TRANSACTION_UNKNOWN_value, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_TRANSACTION_UNKNOWN_name); + + zend_attribute *attribute_Deprecated_const_TRANSACTION_IDLE_0 = zend_add_class_constant_attribute(class_entry, const_TRANSACTION_IDLE, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_TRANSACTION_IDLE_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_TRANSACTION_IDLE_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_TRANSACTION_IDLE_0_arg1_str = zend_string_init("as it has no effect", strlen("as it has no effect"), 1); + ZVAL_STR(&attribute_Deprecated_const_TRANSACTION_IDLE_0->args[1].value, attribute_Deprecated_const_TRANSACTION_IDLE_0_arg1_str); + attribute_Deprecated_const_TRANSACTION_IDLE_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_TRANSACTION_ACTIVE_0 = zend_add_class_constant_attribute(class_entry, const_TRANSACTION_ACTIVE, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_TRANSACTION_ACTIVE_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_TRANSACTION_ACTIVE_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_TRANSACTION_ACTIVE_0->args[1].value, attribute_Deprecated_const_TRANSACTION_IDLE_0_arg1_str); + attribute_Deprecated_const_TRANSACTION_ACTIVE_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_TRANSACTION_INTRANS_0 = zend_add_class_constant_attribute(class_entry, const_TRANSACTION_INTRANS, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_TRANSACTION_INTRANS_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_TRANSACTION_INTRANS_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_TRANSACTION_INTRANS_0->args[1].value, attribute_Deprecated_const_TRANSACTION_IDLE_0_arg1_str); + attribute_Deprecated_const_TRANSACTION_INTRANS_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_TRANSACTION_INERROR_0 = zend_add_class_constant_attribute(class_entry, const_TRANSACTION_INERROR, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_TRANSACTION_INERROR_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_TRANSACTION_INERROR_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_TRANSACTION_INERROR_0->args[1].value, attribute_Deprecated_const_TRANSACTION_IDLE_0_arg1_str); + attribute_Deprecated_const_TRANSACTION_INERROR_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_TRANSACTION_UNKNOWN_0 = zend_add_class_constant_attribute(class_entry, const_TRANSACTION_UNKNOWN, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_TRANSACTION_UNKNOWN_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_const_TRANSACTION_UNKNOWN_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_TRANSACTION_UNKNOWN_0->args[1].value, attribute_Deprecated_const_TRANSACTION_IDLE_0_arg1_str); + attribute_Deprecated_const_TRANSACTION_UNKNOWN_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + return class_entry; } diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 4895463db4b08..be865c1f86838 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -39,8 +39,14 @@ static bool pgsql_handle_in_transaction(pdo_dbh_t *dbh); static char * _pdo_pgsql_trim_message(const char *message, int persistent) { - size_t i = strlen(message)-1; + size_t i = strlen(message); char *tmp; + if (UNEXPECTED(i == 0)) { + tmp = pemalloc(1, persistent); + tmp[0] = '\0'; + return tmp; + } + --i; if (i>1 && (message[i-1] == '\r' || message[i-1] == '\n') && message[i] == '.') { --i; @@ -378,11 +384,15 @@ static zend_string* pgsql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquo zend_string *quoted_str; pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; size_t tmp_len; + int err; switch (paramtype) { case PDO_PARAM_LOB: /* escapedlen returned by PQescapeBytea() accounts for trailing 0 */ escaped = PQescapeByteaConn(H->server, (unsigned char *)ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), &tmp_len); + if (escaped == NULL) { + return NULL; + } quotedlen = tmp_len + 1; quoted = emalloc(quotedlen + 1); memcpy(quoted+1, escaped, quotedlen-2); @@ -394,7 +404,11 @@ static zend_string* pgsql_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquo default: quoted = safe_emalloc(2, ZSTR_LEN(unquoted), 3); quoted[0] = '\''; - quotedlen = PQescapeStringConn(H->server, quoted + 1, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), NULL); + quotedlen = PQescapeStringConn(H->server, quoted + 1, ZSTR_VAL(unquoted), ZSTR_LEN(unquoted), &err); + if (err) { + efree(quoted); + return NULL; + } quoted[quotedlen + 1] = '\''; quoted[quotedlen + 2] = '\0'; quotedlen += 2; diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 3485bd8df0024..f9320fd86ea83 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -526,10 +526,10 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt, ExecStatusType status; switch (ori) { - case PDO_FETCH_ORI_NEXT: spprintf(&ori_str, 0, "NEXT"); break; - case PDO_FETCH_ORI_PRIOR: spprintf(&ori_str, 0, "BACKWARD"); break; - case PDO_FETCH_ORI_FIRST: spprintf(&ori_str, 0, "FIRST"); break; - case PDO_FETCH_ORI_LAST: spprintf(&ori_str, 0, "LAST"); break; + case PDO_FETCH_ORI_NEXT: ori_str = "NEXT"; break; + case PDO_FETCH_ORI_PRIOR: ori_str = "BACKWARD"; break; + case PDO_FETCH_ORI_FIRST: ori_str = "FIRST"; break; + case PDO_FETCH_ORI_LAST: ori_str = "LAST"; break; case PDO_FETCH_ORI_ABS: spprintf(&ori_str, 0, "ABSOLUTE " ZEND_LONG_FMT, offset); break; case PDO_FETCH_ORI_REL: spprintf(&ori_str, 0, "RELATIVE " ZEND_LONG_FMT, offset); break; default: @@ -542,7 +542,9 @@ static int pgsql_stmt_fetch(pdo_stmt_t *stmt, } spprintf(&q, 0, "FETCH %s FROM %s", ori_str, S->cursor_name); - efree(ori_str); + if (ori == PDO_FETCH_ORI_ABS || ori == PDO_FETCH_ORI_REL) { + efree(ori_str); + } S->result = PQexec(S->H->server, q); efree(q); status = PQresultStatus(S->result); diff --git a/ext/pdo_pgsql/tests/bug68199.phpt b/ext/pdo_pgsql/tests/bug68199.phpt index 55a83a2bcddf5..8ec73634a07e1 100644 --- a/ext/pdo_pgsql/tests/bug68199.phpt +++ b/ext/pdo_pgsql/tests/bug68199.phpt @@ -80,26 +80,41 @@ var_dump($notify[2]); var_dump($db->pgsqlGetNotify()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::pgsqlGetPid() is deprecated since 8.5, use Pdo\Pgsql::getPid() instead in %s on line %d bool(true) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(false) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(false) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(3) string(16) "channel_bug68199" bool(true) string(7) "payload" + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(3) string(16) "channel_bug68199" bool(true) string(7) "payload" + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(3) string(16) "channel_bug68199" bool(true) string(7) "payload" + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(3) string(16) "channel_bug68199" bool(true) string(7) "payload" + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(6) string(16) "channel_bug68199" bool(true) @@ -107,4 +122,6 @@ string(7) "payload" string(16) "channel_bug68199" bool(true) string(7) "payload" + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(false) diff --git a/ext/pdo_pgsql/tests/bug68371.phpt b/ext/pdo_pgsql/tests/bug68371.phpt index 6569abf3071fd..13fd1913274d5 100644 --- a/ext/pdo_pgsql/tests/bug68371.phpt +++ b/ext/pdo_pgsql/tests/bug68371.phpt @@ -18,7 +18,7 @@ $pdo->setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $attrs = array( // Extensive test: default value and set+get values PDO::ATTR_EMULATE_PREPARES => array(null, true, false), - PDO::PGSQL_ATTR_DISABLE_PREPARES => array(null, true, false), + Pdo\Pgsql::ATTR_DISABLE_PREPARES => array(null, true, false), // Just test the default PDO::ATTR_AUTOCOMMIT => array(null), diff --git a/ext/pdo_pgsql/tests/bug73959.phpt b/ext/pdo_pgsql/tests/bug73959.phpt index 34b68f9825c73..918743ff4383e 100644 --- a/ext/pdo_pgsql/tests/bug73959.phpt +++ b/ext/pdo_pgsql/tests/bug73959.phpt @@ -15,7 +15,7 @@ require __DIR__ . '/config.inc'; $db = PDOTest::test_factory(__DIR__ . '/common.phpt'); $db->setAttribute(PDO::ATTR_PERSISTENT, false); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -$db->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true); +$db->setAttribute(Pdo\Pgsql::ATTR_DISABLE_PREPARES, true); try { $db->lastInsertId('nonexistent_seq'); diff --git a/ext/pdo_pgsql/tests/copy_from.phpt b/ext/pdo_pgsql/tests/copy_from.phpt index 8480c2961a236..ded3efd9cad2a 100644 --- a/ext/pdo_pgsql/tests/copy_from.phpt +++ b/ext/pdo_pgsql/tests/copy_from.phpt @@ -134,6 +134,8 @@ $db->query('DROP TABLE IF EXISTS test_copy_from CASCADE'); --EXPECTF-- Preparing test file and array for CopyFrom tests Testing pgsqlCopyFromArray() with default parameters + +Deprecated: Method PDO::pgsqlCopyFromArray() is deprecated since 8.5, use Pdo\Pgsql::copyFromArray() instead in %s on line %d bool(true) array(6) { ["a"]=> @@ -178,6 +180,8 @@ array(6) { NULL } Testing pgsqlCopyFromArray() with different field separator and not null indicator + +Deprecated: Method PDO::pgsqlCopyFromArray() is deprecated since 8.5, use Pdo\Pgsql::copyFromArray() instead in %s on line %d bool(true) array(6) { ["a"]=> @@ -222,6 +226,8 @@ array(6) { NULL } Testing pgsqlCopyFromArray() with only selected fields + +Deprecated: Method PDO::pgsqlCopyFromArray() is deprecated since 8.5, use Pdo\Pgsql::copyFromArray() instead in %s on line %d bool(true) array(6) { ["a"]=> @@ -266,8 +272,12 @@ array(6) { NULL } Testing pgsqlCopyFromArray() with error + +Deprecated: Method PDO::pgsqlCopyFromArray() is deprecated since 8.5, use Pdo\Pgsql::copyFromArray() instead in %s on line %d Exception: SQLSTATE[42P01]: Undefined table: 7 %s: %stest_error%s Testing pgsqlCopyFromFile() with default parameters + +Deprecated: Method PDO::pgsqlCopyFromFile() is deprecated since 8.5, use Pdo\Pgsql::copyFromFile() instead in %s on line %d bool(true) array(6) { ["a"]=> @@ -312,6 +322,8 @@ array(6) { NULL } Testing pgsqlCopyFromFile() with different field separator and not null indicator + +Deprecated: Method PDO::pgsqlCopyFromFile() is deprecated since 8.5, use Pdo\Pgsql::copyFromFile() instead in %s on line %d bool(true) array(6) { ["a"]=> @@ -356,6 +368,8 @@ array(6) { NULL } Testing pgsqlCopyFromFile() with only selected fields + +Deprecated: Method PDO::pgsqlCopyFromFile() is deprecated since 8.5, use Pdo\Pgsql::copyFromFile() instead in %s on line %d bool(true) array(6) { ["a"]=> @@ -400,6 +414,10 @@ array(6) { NULL } Testing pgsqlCopyFromFile() with error + +Deprecated: Method PDO::pgsqlCopyFromFile() is deprecated since 8.5, use Pdo\Pgsql::copyFromFile() instead in %s on line %d Exception: SQLSTATE[42P01]: Undefined table: 7 %s: %stest_error%s Testing pgsqlCopyFromFile() with non existing file + +Deprecated: Method PDO::pgsqlCopyFromFile() is deprecated since 8.5, use Pdo\Pgsql::copyFromFile() instead in %s on line %d Exception: SQLSTATE[HY000]: General error: 7 Unable to open the file diff --git a/ext/pdo_pgsql/tests/copy_from_generator.phpt b/ext/pdo_pgsql/tests/copy_from_generator.phpt index a058cb4ff4300..6bfd39a7f2387 100644 --- a/ext/pdo_pgsql/tests/copy_from_generator.phpt +++ b/ext/pdo_pgsql/tests/copy_from_generator.phpt @@ -41,7 +41,8 @@ require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc'; $db = PDOTest::test_factory(__DIR__ . '/common.phpt'); $db->query('DROP TABLE IF EXISTS test_copy_from_generator CASCADE'); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::pgsqlCopyFromArray() is deprecated since 8.5, use Pdo\Pgsql::copyFromArray() instead in %s on line %d array ( 0 => 1, 1 => 1, diff --git a/ext/pdo_pgsql/tests/copy_from_iterator.phpt b/ext/pdo_pgsql/tests/copy_from_iterator.phpt index b507af8914628..bb178d0d66b81 100644 --- a/ext/pdo_pgsql/tests/copy_from_iterator.phpt +++ b/ext/pdo_pgsql/tests/copy_from_iterator.phpt @@ -61,8 +61,11 @@ require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc'; $db = PDOTest::test_factory(__DIR__ . '/common.phpt'); $db->query('DROP TABLE IF EXISTS test_copy_from_traversable CASCADE'); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::pgsqlCopyFromArray() is deprecated since 8.5, use Pdo\Pgsql::copyFromArray() instead in %s on line %d PDO::pgsqlCopyFromArray(): Argument #2 ($rows) must be of type Traversable|array, stdClass given + +Deprecated: Method PDO::pgsqlCopyFromArray() is deprecated since 8.5, use Pdo\Pgsql::copyFromArray() instead in %s on line %d array ( 0 => 1, 1 => 1, diff --git a/ext/pdo_pgsql/tests/copy_to.phpt b/ext/pdo_pgsql/tests/copy_to.phpt index 0f2d8cd7e9c7a..02707006d2a86 100644 --- a/ext/pdo_pgsql/tests/copy_to.phpt +++ b/ext/pdo_pgsql/tests/copy_to.phpt @@ -87,6 +87,8 @@ $db->exec('DROP TABLE test_copy_to'); --EXPECTF-- Preparing test table for CopyTo tests Testing pgsqlCopyToArray() with default parameters + +Deprecated: Method PDO::pgsqlCopyToArray() is deprecated since 8.5, use Pdo\Pgsql::copyToArray() instead in %s on line %d array(3) { [0]=> string(19) "0 test insert 0 \N @@ -99,6 +101,8 @@ array(3) { " } Testing pgsqlCopyToArray() with different field separator and not null indicator + +Deprecated: Method PDO::pgsqlCopyToArray() is deprecated since 8.5, use Pdo\Pgsql::copyToArray() instead in %s on line %d array(3) { [0]=> string(21) "0;test insert 0;NULL @@ -111,6 +115,8 @@ array(3) { " } Testing pgsqlCopyToArray() with only selected fields + +Deprecated: Method PDO::pgsqlCopyToArray() is deprecated since 8.5, use Pdo\Pgsql::copyToArray() instead in %s on line %d array(3) { [0]=> string(7) "0;NULL @@ -123,23 +129,35 @@ array(3) { " } Testing pgsqlCopyToArray() with error + +Deprecated: Method PDO::pgsqlCopyToArray() is deprecated since 8.5, use Pdo\Pgsql::copyToArray() instead in %s on line %d Exception: SQLSTATE[42P01]: Undefined table: 7 %s: %stest_error%s Testing pgsqlCopyToFile() with default parameters + +Deprecated: Method PDO::pgsqlCopyToFile() is deprecated since 8.5, use Pdo\Pgsql::copyToFile() instead in %s on line %d bool(true) 0 test insert 0 \N 1 test insert 1 \N 2 test insert 2 \N Testing pgsqlCopyToFile() with different field separator and not null indicator + +Deprecated: Method PDO::pgsqlCopyToFile() is deprecated since 8.5, use Pdo\Pgsql::copyToFile() instead in %s on line %d bool(true) 0;test insert 0;NULL 1;test insert 1;NULL 2;test insert 2;NULL Testing pgsqlCopyToFile() with only selected fields + +Deprecated: Method PDO::pgsqlCopyToFile() is deprecated since 8.5, use Pdo\Pgsql::copyToFile() instead in %s on line %d bool(true) 0;NULL 1;NULL 2;NULL Testing pgsqlCopyToFile() with error + +Deprecated: Method PDO::pgsqlCopyToFile() is deprecated since 8.5, use Pdo\Pgsql::copyToFile() instead in %s on line %d Exception: SQLSTATE[42P01]: Undefined table: 7 %s: %stest_error%s Testing pgsqlCopyToFile() to unwritable file + +Deprecated: Method PDO::pgsqlCopyToFile() is deprecated since 8.5, use Pdo\Pgsql::copyToFile() instead in %s on line %d Exception: SQLSTATE[HY000]: General error: 7 Unable to open the file for writing diff --git a/ext/pdo_pgsql/tests/disable_prepares.phpt b/ext/pdo_pgsql/tests/disable_prepares.phpt index 58f3a4b00c1fb..b184e9bc6db68 100644 --- a/ext/pdo_pgsql/tests/disable_prepares.phpt +++ b/ext/pdo_pgsql/tests/disable_prepares.phpt @@ -28,7 +28,7 @@ $stmt->execute(); $first = $stmt->fetchAll(); $stmt3 = $db->prepare("SELECT (?)::int4", array( - PDO::PGSQL_ATTR_DISABLE_PREPARES => true)); + Pdo\Pgsql::ATTR_DISABLE_PREPARES => true)); $stmt3->execute(array(3)); var_dump($stmt3->fetch()); $stmt3->execute(array(4)); diff --git a/ext/pdo_pgsql/tests/getnotify.phpt b/ext/pdo_pgsql/tests/getnotify.phpt index fca15879d19d4..fe6a34b7f95eb 100644 --- a/ext/pdo_pgsql/tests/getnotify.phpt +++ b/ext/pdo_pgsql/tests/getnotify.phpt @@ -84,29 +84,50 @@ var_dump($diff < 1 || abs(1 - abs($diff)) < .05); var_dump(count($notify)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::pgsqlGetPid() is deprecated since 8.5, use Pdo\Pgsql::getPid() instead in %s on line %d bool(true) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(false) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(false) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(2) string(17) "channel_getnotify" bool(true) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(2) string(17) "channel_getnotify" bool(true) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(2) string(17) "channel_getnotify" bool(true) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(2) string(17) "channel_getnotify" bool(true) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d int(4) string(17) "channel_getnotify" bool(true) string(17) "channel_getnotify" bool(true) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(false) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(true) bool(false) + +Deprecated: Method PDO::pgsqlGetNotify() is deprecated since 8.5, use Pdo\Pgsql::getNotify() instead in %s on line %d bool(true) int(2) diff --git a/ext/pdo_pgsql/tests/gh15287.phpt b/ext/pdo_pgsql/tests/gh15287.phpt index 72bcc44b363b4..821c22a8f1c5a 100644 --- a/ext/pdo_pgsql/tests/gh15287.phpt +++ b/ext/pdo_pgsql/tests/gh15287.phpt @@ -75,8 +75,8 @@ for ($i = -1; ++$i < 5;) { while (($re = $stmt->fetch())) { $res[] = $re; // Memory introspection relies on an optionally-compiled constant. - if (defined('PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE')) { - $mem = $stmt->getAttribute(PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE); + if (defined('Pdo\Pgsql::ATTR_RESULT_MEMORY_SIZE')) { + $mem = $stmt->getAttribute(Pdo\Pgsql::ATTR_RESULT_MEMORY_SIZE); } else { // If not there emulate a return value which validates our test. $mem = $lazy ? 0 : 1; diff --git a/ext/pdo_pgsql/tests/gh9411.phpt b/ext/pdo_pgsql/tests/gh9411.phpt index 5fe19c3560d40..2e8eadf8d3e0c 100644 --- a/ext/pdo_pgsql/tests/gh9411.phpt +++ b/ext/pdo_pgsql/tests/gh9411.phpt @@ -34,9 +34,18 @@ var_dump($lob = $db->pgsqlLOBOpen($oid, 'wb')); var_dump(fgets($lob)); ?> --EXPECTF-- +Deprecated: Method PDO::pgsqlLOBCreate() is deprecated since 8.5, use Pdo\Pgsql::lobCreate() instead in %s on line %d + +Deprecated: Method PDO::pgsqlLOBOpen() is deprecated since 8.5, use Pdo\Pgsql::lobOpen() instead in %s on line %d resource(%d) of type (stream) resource(%d) of type (Unknown) + +Deprecated: Method PDO::pgsqlLOBCreate() is deprecated since 8.5, use Pdo\Pgsql::lobCreate() instead in %s on line %d + +Deprecated: Method PDO::pgsqlLOBOpen() is deprecated since 8.5, use Pdo\Pgsql::lobOpen() instead in %s on line %d resource(%d) of type (stream) resource(%d) of type (Unknown) + +Deprecated: Method PDO::pgsqlLOBOpen() is deprecated since 8.5, use Pdo\Pgsql::lobOpen() instead in %s on line %d resource(%d) of type (stream) string(4) "test" diff --git a/ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt b/ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt new file mode 100644 index 0000000000000..8566a26753b40 --- /dev/null +++ b/ext/pdo_pgsql/tests/ghsa-hrwm-9436-5mv3.phpt @@ -0,0 +1,24 @@ +--TEST-- +#GHSA-hrwm-9436-5mv3: pdo_pgsql extension does not check for errors during escaping +--EXTENSIONS-- +pdo +pdo_pgsql +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$invalid = "ABC\xff\x30';"; +var_dump($db->quote($invalid)); + +?> +--EXPECT-- +bool(false) diff --git a/ext/pdo_pgsql/tests/is_in_transaction.phpt b/ext/pdo_pgsql/tests/is_in_transaction.phpt index 440044f66a578..982357db9210a 100644 --- a/ext/pdo_pgsql/tests/is_in_transaction.phpt +++ b/ext/pdo_pgsql/tests/is_in_transaction.phpt @@ -19,7 +19,7 @@ $db->exec('CREATE TABLE test_is_in_transaction (a integer not null primary key, $db->beginTransaction(); try { -echo "Test PDO::PGSQL_TRANSACTION_INTRANS\n"; +echo "Test Pdo\Pgsql::TRANSACTION_INTRANS\n"; var_dump($db->inTransaction()); $stmt = $db->prepare("INSERT INTO test_is_in_transaction (a, b) values (?, ?)"); @@ -29,7 +29,7 @@ $stmt->execute(); $db->commit(); -echo "Test PDO::PGSQL_TRANSACTION_IDLE\n"; +echo "Test Pdo\Pgsql::TRANSACTION_IDLE\n"; var_dump($db->inTransaction()); $db->beginTransaction(); @@ -40,13 +40,13 @@ $stmt->bindValue(1, "error"); $stmt->bindValue(2, "test insert"); $stmt->execute(); } catch (Exception $e) { - /* We catch the exception because the execute will give error and we must test the PDO::PGSQL_TRANSACTION_ERROR */ - echo "Test PDO::PGSQL_TRANSACTION_INERROR\n"; + /* We catch the exception because the execute will give error and we must test the Pdo\Pgsql::TRANSACTION_ERROR */ + echo "Test Pdo\Pgsql::TRANSACTION_INERROR\n"; var_dump($db->inTransaction()); $db->rollBack(); } -echo "Test PDO::PGSQL_TRANSACTION_IDLE\n"; +echo "Test Pdo\Pgsql::TRANSACTION_IDLE\n"; var_dump($db->inTransaction()); } catch (Exception $e) { @@ -62,11 +62,11 @@ $db = PDOTest::test_factory(__DIR__ . '/common.phpt'); $db->exec('DROP TABLE test_is_in_transaction'); ?> --EXPECT-- -Test PDO::PGSQL_TRANSACTION_INTRANS +Test Pdo\Pgsql::TRANSACTION_INTRANS bool(true) -Test PDO::PGSQL_TRANSACTION_IDLE +Test Pdo\Pgsql::TRANSACTION_IDLE bool(false) -Test PDO::PGSQL_TRANSACTION_INERROR +Test Pdo\Pgsql::TRANSACTION_INERROR bool(true) -Test PDO::PGSQL_TRANSACTION_IDLE +Test Pdo\Pgsql::TRANSACTION_IDLE bool(false) diff --git a/ext/pdo_pgsql/tests/large_objects.phpt b/ext/pdo_pgsql/tests/large_objects.phpt index ff3248fbdb341..86149ce1b6a8b 100644 --- a/ext/pdo_pgsql/tests/large_objects.phpt +++ b/ext/pdo_pgsql/tests/large_objects.phpt @@ -83,7 +83,10 @@ require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc'; $db = PDOTest::test_factory(__DIR__ . '/common.phpt'); $db->exec('DROP TABLE test_large_objects'); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::pgsqlLOBCreate() is deprecated since 8.5, use Pdo\Pgsql::lobCreate() instead in %s on line %d + +Deprecated: Method PDO::pgsqlLOBOpen() is deprecated since 8.5, use Pdo\Pgsql::lobOpen() instead in %s on line %d Fetching: int(1) string(11) "Hello dude @@ -97,3 +100,5 @@ Fetching NO bind: int(1) bool(true) Fetched! + +Deprecated: Method PDO::pgsqlLOBUnlink() is deprecated since 8.5, use Pdo\Pgsql::lobUnlink() instead in %s on line %d diff --git a/ext/pdo_pgsql/tests/php_8.5_deprecations.phpt b/ext/pdo_pgsql/tests/php_8.5_deprecations.phpt new file mode 100644 index 0000000000000..816850853e144 --- /dev/null +++ b/ext/pdo_pgsql/tests/php_8.5_deprecations.phpt @@ -0,0 +1,15 @@ +--TEST-- +PDO_pgsql: PHP 8.5 deprecations +--EXTENSIONS-- +pdo_pgsql +--FILE-- + +--EXPECTF-- +Deprecated: Constant PDO::PGSQL_ATTR_DISABLE_PREPARES is deprecated since 8.5, use Pdo\Pgsql::ATTR_DISABLE_PREPARES instead in %s on line %d +int(1000) diff --git a/ext/pdo_pgsql/tests/transations_deprecations.phpt b/ext/pdo_pgsql/tests/transations_deprecations.phpt new file mode 100644 index 0000000000000..7aa51b47f7698 --- /dev/null +++ b/ext/pdo_pgsql/tests/transations_deprecations.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test PDO::PGSQL_TRANSACTION* constants. +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Deprecated: Constant PDO::PGSQL_TRANSACTION_IDLE is deprecated since 8.5 in %s on line %d +int(0) + +Deprecated: Constant PDO::PGSQL_TRANSACTION_ACTIVE is deprecated since 8.5 in %s on line %d +int(1) + +Deprecated: Constant PDO::PGSQL_TRANSACTION_INTRANS is deprecated since 8.5 in %s on line %d +int(2) + +Deprecated: Constant PDO::PGSQL_TRANSACTION_INERROR is deprecated since 8.5 in %s on line %d +int(3) + +Deprecated: Constant PDO::PGSQL_TRANSACTION_UNKNOWN is deprecated since 8.5 in %s on line %d +int(4) diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index 023e35a2bc33c..667948fea9f1f 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -404,19 +404,22 @@ PHP_METHOD(Pdo_Sqlite, createCollation) pdo_sqlite_create_collation_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, php_sqlite_collation_callback); } +#define REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, value) \ + REGISTER_PDO_CLASS_CONST_LONG_DEPRECATED_ALIAS_85(base_name, "SQLITE_", "Pdo\\Sqlite::", value) + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(pdo_sqlite) { #ifdef SQLITE_DETERMINISTIC - REGISTER_PDO_CLASS_CONST_LONG("SQLITE_DETERMINISTIC", (zend_long)SQLITE_DETERMINISTIC); + REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("DETERMINISTIC", (zend_long)SQLITE_DETERMINISTIC); #endif - REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_OPEN_FLAGS", (zend_long)PDO_SQLITE_ATTR_OPEN_FLAGS); - REGISTER_PDO_CLASS_CONST_LONG("SQLITE_OPEN_READONLY", (zend_long)SQLITE_OPEN_READONLY); - REGISTER_PDO_CLASS_CONST_LONG("SQLITE_OPEN_READWRITE", (zend_long)SQLITE_OPEN_READWRITE); - REGISTER_PDO_CLASS_CONST_LONG("SQLITE_OPEN_CREATE", (zend_long)SQLITE_OPEN_CREATE); - REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_READONLY_STATEMENT", (zend_long)PDO_SQLITE_ATTR_READONLY_STATEMENT); - REGISTER_PDO_CLASS_CONST_LONG("SQLITE_ATTR_EXTENDED_RESULT_CODES", (zend_long)PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES); + REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_OPEN_FLAGS", (zend_long)PDO_SQLITE_ATTR_OPEN_FLAGS); + REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("OPEN_READONLY", (zend_long)SQLITE_OPEN_READONLY); + REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("OPEN_READWRITE", (zend_long)SQLITE_OPEN_READWRITE); + REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("OPEN_CREATE", (zend_long)SQLITE_OPEN_CREATE); + REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_READONLY_STATEMENT", (zend_long)PDO_SQLITE_ATTR_READONLY_STATEMENT); + REGISTER_PDO_SQLITE_CLASS_CONST_LONG_DEPRECATED_ALIAS_85("ATTR_EXTENDED_RESULT_CODES", (zend_long)PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES); pdosqlite_ce = register_class_Pdo_Sqlite(pdo_dbh_ce); pdosqlite_ce->create_object = pdo_dbh_new; diff --git a/ext/pdo_sqlite/pdo_sqlite.stub.php b/ext/pdo_sqlite/pdo_sqlite.stub.php index 4af2d8c55260b..53f1ceba427b0 100644 --- a/ext/pdo_sqlite/pdo_sqlite.stub.php +++ b/ext/pdo_sqlite/pdo_sqlite.stub.php @@ -39,6 +39,13 @@ class Sqlite extends \PDO /** @cvalue PDO_SQLITE_ATTR_EXPLAIN_STATEMENT */ public const int ATTR_EXPLAIN_STATEMENT = UNKNOWN; + /** @cvalue PDO_SQLITE_ATTR_TRANSACTION_MODE */ + public const int ATTR_TRANSACTION_MODE = UNKNOWN; + + public const int TRANSACTION_MODE_DEFERRED = 0; + public const int TRANSACTION_MODE_IMMEDIATE = 1; + public const int TRANSACTION_MODE_EXCLUSIVE = 2; + #if SQLITE_VERSION_NUMBER >= 3043000 public const int EXPLAIN_MODE_PREPARED = 0; public const int EXPLAIN_MODE_EXPLAIN = 1; diff --git a/ext/pdo_sqlite/pdo_sqlite_arginfo.h b/ext/pdo_sqlite/pdo_sqlite_arginfo.h index e2cd71723706e..44ec8bc327186 100644 --- a/ext/pdo_sqlite/pdo_sqlite_arginfo.h +++ b/ext/pdo_sqlite/pdo_sqlite_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c1d4ef325ecb8c8cb312910e8091ca003dc2603a */ + * Stub hash: 721c46905fa8fb1e18d7196ed85c37f56049ea33 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Pdo_Sqlite_createAggregate, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) @@ -121,6 +121,30 @@ static zend_class_entry *register_class_Pdo_Sqlite(zend_class_entry *class_entry zend_string *const_ATTR_EXPLAIN_STATEMENT_name = zend_string_init_interned("ATTR_EXPLAIN_STATEMENT", sizeof("ATTR_EXPLAIN_STATEMENT") - 1, 1); zend_declare_typed_class_constant(class_entry, const_ATTR_EXPLAIN_STATEMENT_name, &const_ATTR_EXPLAIN_STATEMENT_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(const_ATTR_EXPLAIN_STATEMENT_name); + + zval const_ATTR_TRANSACTION_MODE_value; + ZVAL_LONG(&const_ATTR_TRANSACTION_MODE_value, PDO_SQLITE_ATTR_TRANSACTION_MODE); + zend_string *const_ATTR_TRANSACTION_MODE_name = zend_string_init_interned("ATTR_TRANSACTION_MODE", sizeof("ATTR_TRANSACTION_MODE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_ATTR_TRANSACTION_MODE_name, &const_ATTR_TRANSACTION_MODE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_ATTR_TRANSACTION_MODE_name); + + zval const_TRANSACTION_MODE_DEFERRED_value; + ZVAL_LONG(&const_TRANSACTION_MODE_DEFERRED_value, 0); + zend_string *const_TRANSACTION_MODE_DEFERRED_name = zend_string_init_interned("TRANSACTION_MODE_DEFERRED", sizeof("TRANSACTION_MODE_DEFERRED") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_TRANSACTION_MODE_DEFERRED_name, &const_TRANSACTION_MODE_DEFERRED_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_TRANSACTION_MODE_DEFERRED_name); + + zval const_TRANSACTION_MODE_IMMEDIATE_value; + ZVAL_LONG(&const_TRANSACTION_MODE_IMMEDIATE_value, 1); + zend_string *const_TRANSACTION_MODE_IMMEDIATE_name = zend_string_init_interned("TRANSACTION_MODE_IMMEDIATE", sizeof("TRANSACTION_MODE_IMMEDIATE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_TRANSACTION_MODE_IMMEDIATE_name, &const_TRANSACTION_MODE_IMMEDIATE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_TRANSACTION_MODE_IMMEDIATE_name); + + zval const_TRANSACTION_MODE_EXCLUSIVE_value; + ZVAL_LONG(&const_TRANSACTION_MODE_EXCLUSIVE_value, 2); + zend_string *const_TRANSACTION_MODE_EXCLUSIVE_name = zend_string_init_interned("TRANSACTION_MODE_EXCLUSIVE", sizeof("TRANSACTION_MODE_EXCLUSIVE") - 1, 1); + zend_declare_typed_class_constant(class_entry, const_TRANSACTION_MODE_EXCLUSIVE_name, &const_TRANSACTION_MODE_EXCLUSIVE_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(const_TRANSACTION_MODE_EXCLUSIVE_name); #if SQLITE_VERSION_NUMBER >= 3043000 zval const_EXPLAIN_MODE_PREPARED_value; diff --git a/ext/pdo_sqlite/php_pdo_sqlite.h b/ext/pdo_sqlite/php_pdo_sqlite.h index 1bba9e3556a7b..c29a81ebb2409 100644 --- a/ext/pdo_sqlite/php_pdo_sqlite.h +++ b/ext/pdo_sqlite/php_pdo_sqlite.h @@ -27,6 +27,12 @@ extern zend_module_entry pdo_sqlite_module_entry; #include "TSRM.h" #endif +enum pdo_sqlite_transaction_mode { + PDO_SQLITE_TRANSACTION_MODE_DEFERRED = 0, + PDO_SQLITE_TRANSACTION_MODE_IMMEDIATE = 1, + PDO_SQLITE_TRANSACTION_MODE_EXCLUSIVE = 2 +}; + PHP_MINIT_FUNCTION(pdo_sqlite); PHP_MSHUTDOWN_FUNCTION(pdo_sqlite); PHP_RINIT_FUNCTION(pdo_sqlite); diff --git a/ext/pdo_sqlite/php_pdo_sqlite_int.h b/ext/pdo_sqlite/php_pdo_sqlite_int.h index 69ac003356b87..0cb09cfaa4fb4 100644 --- a/ext/pdo_sqlite/php_pdo_sqlite_int.h +++ b/ext/pdo_sqlite/php_pdo_sqlite_int.h @@ -51,6 +51,7 @@ typedef struct { struct pdo_sqlite_func *funcs; struct pdo_sqlite_collation *collations; zend_fcall_info_cache authorizer_fcc; + enum pdo_sqlite_transaction_mode transaction_mode; } pdo_sqlite_db_handle; typedef struct { @@ -75,7 +76,8 @@ enum { PDO_SQLITE_ATTR_READONLY_STATEMENT, PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES, PDO_SQLITE_ATTR_BUSY_STATEMENT, - PDO_SQLITE_ATTR_EXPLAIN_STATEMENT + PDO_SQLITE_ATTR_EXPLAIN_STATEMENT, + PDO_SQLITE_ATTR_TRANSACTION_MODE }; typedef int pdo_sqlite_create_collation_callback(void*, int, const void*, int, const void*); diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 2c907a34f489b..537aefa9be1e5 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -255,7 +255,20 @@ static bool sqlite_handle_begin(pdo_dbh_t *dbh) { pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data; - if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, NULL) != SQLITE_OK) { + const char *begin_statement = "BEGIN"; + switch (H->transaction_mode) { + case PDO_SQLITE_TRANSACTION_MODE_DEFERRED: + begin_statement = "BEGIN DEFERRED TRANSACTION"; + break; + case PDO_SQLITE_TRANSACTION_MODE_IMMEDIATE: + begin_statement = "BEGIN IMMEDIATE TRANSACTION"; + break; + case PDO_SQLITE_TRANSACTION_MODE_EXCLUSIVE: + begin_statement = "BEGIN EXCLUSIVE TRANSACTION"; + break; + } + + if (sqlite3_exec(H->db, begin_statement, NULL, NULL, NULL) != SQLITE_OK) { pdo_sqlite_error(dbh); return false; } @@ -286,11 +299,16 @@ static bool sqlite_handle_rollback(pdo_dbh_t *dbh) static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value) { + pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data; + switch (attr) { case PDO_ATTR_CLIENT_VERSION: case PDO_ATTR_SERVER_VERSION: ZVAL_STRING(return_value, (char *)sqlite3_libversion()); break; + case PDO_SQLITE_ATTR_TRANSACTION_MODE: + ZVAL_LONG(return_value, H->transaction_mode); + break; default: return 0; @@ -326,6 +344,19 @@ static bool pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val) } sqlite3_extended_result_codes(H->db, lval); return true; + case PDO_SQLITE_ATTR_TRANSACTION_MODE: + if (!pdo_get_long_param(&lval, val)) { + return false; + } + switch (lval) { + case PDO_SQLITE_TRANSACTION_MODE_DEFERRED: + case PDO_SQLITE_TRANSACTION_MODE_IMMEDIATE: + case PDO_SQLITE_TRANSACTION_MODE_EXCLUSIVE: + H->transaction_mode = lval; + return true; + default: + return false; + } } return false; } diff --git a/ext/pdo_sqlite/tests/bug60104.phpt b/ext/pdo_sqlite/tests/bug60104.phpt index b69be4681ad1b..51ff2acf427f3 100644 --- a/ext/pdo_sqlite/tests/bug60104.phpt +++ b/ext/pdo_sqlite/tests/bug60104.phpt @@ -15,5 +15,8 @@ setUp(); setUp(); echo "done"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d done diff --git a/ext/pdo_sqlite/tests/bug70221.phpt b/ext/pdo_sqlite/tests/bug70221.phpt index 5c9d9453048d5..b8e0a20a48a75 100644 --- a/ext/pdo_sqlite/tests/bug70221.phpt +++ b/ext/pdo_sqlite/tests/bug70221.phpt @@ -16,5 +16,6 @@ unset($db); $dbfile = __DIR__ . '/test.sqlite'; unlink($dbfile); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d Everything is fine, no exceptions here diff --git a/ext/pdo_sqlite/tests/gc.phpt b/ext/pdo_sqlite/tests/gc.phpt index b5fbad62dab71..6e60de256f638 100644 --- a/ext/pdo_sqlite/tests/gc.phpt +++ b/ext/pdo_sqlite/tests/gc.phpt @@ -18,5 +18,10 @@ $obj->a->sqliteCreateCollation('col', function() use ($obj) {}); ?> ===DONE=== ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateAggregate() is deprecated since 8.5, use Pdo\Sqlite::createAggregate() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateCollation() is deprecated since 8.5, use Pdo\Sqlite::createCollation() instead in %s on line %d ===DONE=== diff --git a/ext/pdo_sqlite/tests/gh13998.phpt b/ext/pdo_sqlite/tests/gh13998.phpt index c87b4acdd214b..80ebedb1ffb2b 100644 --- a/ext/pdo_sqlite/tests/gh13998.phpt +++ b/ext/pdo_sqlite/tests/gh13998.phpt @@ -21,5 +21,6 @@ try { echo 'done!'; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateAggregate() is deprecated since 8.5, use Pdo\Sqlite::createAggregate() instead in %s on line %d done! diff --git a/ext/pdo_sqlite/tests/pdo_sqlite___construct_uri.phpt b/ext/pdo_sqlite/tests/pdo_sqlite___construct_uri.phpt new file mode 100644 index 0000000000000..7fc686b214723 --- /dev/null +++ b/ext/pdo_sqlite/tests/pdo_sqlite___construct_uri.phpt @@ -0,0 +1,48 @@ +--TEST-- +PDO_sqlite: PDO->__construct() - URI +--EXTENSIONS-- +pdo_sqlite +--FILE-- +getMessage(), PHP_EOL; +} + +clearstatcache(); +var_dump(file_exists($dbFile)); + +?> +--CLEAN-- + +--EXPECTF-- +bool(false) + +Deprecated: Looking up the DSN from a URI is deprecated due to possible security concerns with DSNs coming from remote URIs in %s on line %d +bool(true) +bool(false) +ErrorException: Looking up the DSN from a URI is deprecated due to possible security concerns with DSNs coming from remote URIs +bool(false) diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate.phpt index 3ecc0ccddc991..1a620d6b9d5f6 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate.phpt @@ -19,7 +19,8 @@ foreach ($db->query('SELECT testing(name) FROM test_pdo_sqlite_createaggregate') } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateAggregate() is deprecated since 8.5, use Pdo\Sqlite::createAggregate() instead in %s on line %d array(2) { ["testing(name)"]=> string(2) "12" diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate_002.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate_002.phpt index 4fa3578fef08b..192eabbf74fd0 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate_002.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createaggregate_002.phpt @@ -19,6 +19,9 @@ try { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateAggregate() is deprecated since 8.5, use Pdo\Sqlite::createAggregate() instead in %s on line %d PDO::sqliteCreateAggregate(): Argument #2 ($step) must be a valid callback, function "a" not found or invalid function name + +Deprecated: Method PDO::sqliteCreateAggregate() is deprecated since 8.5, use Pdo\Sqlite::createAggregate() instead in %s on line %d PDO::sqliteCreateAggregate(): Argument #3 ($finalize) must be a valid callback, function "" not found or invalid function name diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt index fdfb8dda448fd..14a2c2e0d0233 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createcollation.phpt @@ -32,11 +32,14 @@ try { echo $e->getMessage(), PHP_EOL; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateCollation() is deprecated since 8.5, use Pdo\Sqlite::createCollation() instead in %s on line %d 1 2 10 1 10 2 + +Deprecated: Method PDO::sqliteCreateCollation() is deprecated since 8.5, use Pdo\Sqlite::createCollation() instead in %s on line %d PDO::query(): Return value of the collation callback must be of type int, string returned diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction.phpt index bda7ab0b41555..b2cb073cb58f1 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction.phpt @@ -20,7 +20,8 @@ foreach ($db->query('SELECT testing(name) FROM test_pdo_sqlite_createfunction') } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d array(2) { ["testing(name)"]=> string(3) "php" diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_002.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_002.phpt index 4ebba65be4a9f..ead2f7b6a830d 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_002.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_002.phpt @@ -17,5 +17,6 @@ try { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d PDO::sqliteCreateFunction(): Argument #2 ($callback) must be a valid callback, function "bar" not found or invalid function name diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt index f9312bcee69e9..6f507789dbf27 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt @@ -4,7 +4,7 @@ PDO_sqlite: Testing sqliteCreateFunction() with flags pdo_sqlite --SKIPIF-- --FILE-- query('CREATE TABLE test_pdo_sqlite_createfunction_with_flags (id INT AUTO $db->query('INSERT INTO test_pdo_sqlite_createfunction_with_flags VALUES (NULL, "PHP"), (NULL, "PHP6")'); -$db->sqliteCreateFunction('testing', function($v) { return strtolower($v); }, 1, PDO::SQLITE_DETERMINISTIC); +$db->sqliteCreateFunction('testing', function($v) { return strtolower($v); }, 1, Pdo\Sqlite::DETERMINISTIC); foreach ($db->query('SELECT testing(name) FROM test_pdo_sqlite_createfunction_with_flags') as $row) { @@ -24,7 +24,8 @@ foreach ($db->query('SELECT testing(name) FROM test_pdo_sqlite_createfunction_wi } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d array(2) { ["testing(name)"]=> string(3) "php" diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt index 19f3bc1427bf7..bbdc65275558d 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_extendederror_attr.phpt @@ -1,5 +1,5 @@ --TEST-- -PDO_sqlite: Testing PDO_SQLITE_ATTR_EXTENDED_RESULT_CODES +PDO_sqlite: Testing Pdo\Sqlite::ATTR_EXTENDED_RESULT_CODES --EXTENSIONS-- pdo_sqlite --FILE-- @@ -23,7 +23,7 @@ echo sprintf("Second Error Info: SQLSTATE Error Code: (%s), Driver Specific Erro echo "Creating new PDO with Extended Result Codes turned on" . PHP_EOL; -$db = new PDO('sqlite::memory:', '', '', [PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES => TRUE]); +$db = new PDO('sqlite::memory:', '', '', [Pdo\Sqlite::ATTR_EXTENDED_RESULT_CODES => TRUE]); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $db->exec("CREATE TABLE dog ( id INTEGER PRIMARY KEY, name TEXT, annoying INTEGER )"); diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_open_flags.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_open_flags.phpt index 772b1d9a76b05..00e1153fa91a0 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_open_flags.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_open_flags.phpt @@ -12,7 +12,7 @@ $db = new PDO('sqlite:' . $filename, null, null, [PDO::ATTR_ERRMODE => PDO::ERRM var_dump($db->exec('CREATE TABLE test_sqlite_open_flags (id INT);')); -$db = new PDO('sqlite:' . $filename, null, null, [PDO::SQLITE_ATTR_OPEN_FLAGS => PDO::SQLITE_OPEN_READONLY, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); +$db = new PDO('sqlite:' . $filename, null, null, [Pdo\Sqlite::ATTR_OPEN_FLAGS => Pdo\Sqlite::OPEN_READONLY, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); var_dump($db->exec('CREATE TABLE test_sqlite_open_flags_2 (id INT);')); ?> diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_statement_getattribute.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_statement_getattribute.phpt index 21b19654977fe..af6f3ad024b71 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_statement_getattribute.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_statement_getattribute.phpt @@ -9,11 +9,11 @@ $db = new PDO('sqlite::memory:'); $st = $db->prepare('SELECT 1;'); -var_dump($st->getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT)); +var_dump($st->getAttribute(Pdo\Sqlite::ATTR_READONLY_STATEMENT)); $st = $db->prepare('CREATE TABLE test_sqlite_stmt_getattribute (a TEXT);'); -var_dump($st->getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT)); +var_dump($st->getAttribute(Pdo\Sqlite::ATTR_READONLY_STATEMENT)); ?> --EXPECT-- bool(true) diff --git a/ext/pdo_sqlite/tests/php_8.5_deprecations.phpt b/ext/pdo_sqlite/tests/php_8.5_deprecations.phpt new file mode 100644 index 0000000000000..e8e0b34141c7d --- /dev/null +++ b/ext/pdo_sqlite/tests/php_8.5_deprecations.phpt @@ -0,0 +1,61 @@ +--TEST-- +PDO_sqlite: PHP 8.5 deprecations +--EXTENSIONS-- +pdo_sqlite +--FILE-- +sqliteCreateFunction('test1', function(){}); +$pdo->sqliteCreateAggregate('test2', function(){}, function(){}); +$pdo->sqliteCreateCollation('test3', function(){}); + +$pdo = new PDO("sqlite::memory:", options: [PDO::ATTR_PERSISTENT => true]); +$pdo->sqliteCreateFunction('test1', function(){}); +$pdo->sqliteCreateAggregate('test2', function(){}, function(){}); +$pdo->sqliteCreateCollation('test3', function(){}); + +?> +--EXPECTF-- +Deprecated: Constant PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES is deprecated since 8.5, use Pdo\Sqlite::ATTR_EXTENDED_RESULT_CODES instead in %s on line %d + +Deprecated: Constant PDO::SQLITE_ATTR_OPEN_FLAGS is deprecated since 8.5, use Pdo\Sqlite::ATTR_OPEN_FLAGS instead in %s on line %d + +Deprecated: Constant PDO::SQLITE_ATTR_READONLY_STATEMENT is deprecated since 8.5, use Pdo\Sqlite::ATTR_READONLY_STATEMENT instead in %s on line %d + +Deprecated: Constant PDO::SQLITE_DETERMINISTIC is deprecated since 8.5, use Pdo\Sqlite::DETERMINISTIC instead in %s on line %d + +Deprecated: Constant PDO::SQLITE_OPEN_READONLY is deprecated since 8.5, use Pdo\Sqlite::OPEN_READONLY instead in %s on line %d + +Deprecated: Constant PDO::SQLITE_OPEN_READWRITE is deprecated since 8.5, use Pdo\Sqlite::OPEN_READWRITE instead in %s on line %d + +Deprecated: Constant PDO::SQLITE_OPEN_CREATE is deprecated since 8.5, use Pdo\Sqlite::OPEN_CREATE instead in %s on line %d +int(1002) +int(1000) +int(1001) +int(2048) +int(1) +int(2) +int(4) + +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateAggregate() is deprecated since 8.5, use Pdo\Sqlite::createAggregate() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateCollation() is deprecated since 8.5, use Pdo\Sqlite::createCollation() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateAggregate() is deprecated since 8.5, use Pdo\Sqlite::createAggregate() instead in %s on line %d + +Deprecated: Method PDO::sqliteCreateCollation() is deprecated since 8.5, use Pdo\Sqlite::createCollation() instead in %s on line %d diff --git a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt index 838e2b9bd49b0..c828817d2c3ad 100644 --- a/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt +++ b/ext/pdo_sqlite/tests/subclasses/pdo_sqlite_createfunction_with_flags.phpt @@ -4,7 +4,7 @@ PDO_sqlite: Testing createFunction() with flags pdo_sqlite --SKIPIF-- --FILE-- getAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE) === PDO\Sqlite::TRANSACTION_MODE_DEFERRED); + +// Both should return true - setting DEFERRED +var_dump($pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, PDO\Sqlite::TRANSACTION_MODE_DEFERRED)); +var_dump($pdo->getAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE) === PDO\Sqlite::TRANSACTION_MODE_DEFERRED); + +// Both should return true - setting IMMEDIATE +var_dump($pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, PDO\Sqlite::TRANSACTION_MODE_IMMEDIATE)); +var_dump($pdo->getAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE) === PDO\Sqlite::TRANSACTION_MODE_IMMEDIATE); + +// Both should return true - setting EXCLUSIVE +var_dump($pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, PDO\Sqlite::TRANSACTION_MODE_EXCLUSIVE)); +var_dump($pdo->getAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE) === PDO\Sqlite::TRANSACTION_MODE_EXCLUSIVE); + +// Setting the numeric equivalents of the above. All should return true +var_dump($pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, 0)); +var_dump($pdo->getAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE) === PDO\Sqlite::TRANSACTION_MODE_DEFERRED); +var_dump($pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, 1)); +var_dump($pdo->getAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE) === PDO\Sqlite::TRANSACTION_MODE_IMMEDIATE); +var_dump($pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, 2)); +var_dump($pdo->getAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE) === PDO\Sqlite::TRANSACTION_MODE_EXCLUSIVE); + +// Cannot set a random numeric value +var_dump($pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, 4)); + +// Set $pdo to deferred, try to get immediate transaction in $pdo2. There should be no lock contention +$pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, PDO\Sqlite::TRANSACTION_MODE_DEFERRED); +$pdo->beginTransaction(); +try { + $pdo2->exec('begin immediate transaction'); + $pdo2->rollBack(); + printf("Database is not locked\n"); +} catch (PDOException $e) { + printf("Database is locked: %s\n", $e->getMessage()); +} +$pdo->rollBack(); + +// Set $pdo to immediate, try to get immediate transaction in $pdo2. There SHOULD be lock contention +$pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, PDO\Sqlite::TRANSACTION_MODE_IMMEDIATE); +$pdo->beginTransaction(); +try { + $pdo2->exec('begin immediate transaction'); + printf("Database is not locked\n"); +} catch (PDOException $e) { + printf("Database is locked: %s\n", $e->getMessage()); +} +$pdo->rollBack(); + +// Set $pdo to exclusive, try to get immediate transaction in $pdo2. There SHOULD be lock contention +$pdo->setAttribute(PDO\Sqlite::ATTR_TRANSACTION_MODE, PDO\Sqlite::TRANSACTION_MODE_EXCLUSIVE); +$pdo->beginTransaction(); +try { + $pdo2->exec('begin immediate transaction'); + printf("Database is not locked\n"); +} catch (PDOException $e) { + printf("Database is locked: %s\n", $e->getMessage()); +} +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +Database is not locked +Database is locked: SQLSTATE[HY000]: General error: 6 database table is locked +Database is locked: SQLSTATE[HY000]: General error: 6 database schema is locked: main diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index ba6d660d0307e..d97d0faa1a4b2 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -321,6 +321,10 @@ static void _close_pgsql_plink(zend_resource *rsrc) static void _php_pgsql_notice_handler(void *l, const char *message) { + if (l == NULL) { + /* This connection does not currently have a valid context, ignore this notice */ + return; + } if (PGG(ignore_notices)) { return; } @@ -353,6 +357,11 @@ static int _rollback_transactions(zval *el) link = (PGconn *) rsrc->ptr; + /* unset notice processor if we initially did set it */ + if (PQsetNoticeProcessor(link, NULL, NULL) == _php_pgsql_notice_handler) { + PQsetNoticeProcessor(link, _php_pgsql_notice_handler, NULL); + } + if (PQsetnonblocking(link, 0)) { php_error_docref("ref.pgsql", E_NOTICE, "Cannot set connection to blocking mode"); return -1; @@ -3572,8 +3581,14 @@ PHP_FUNCTION(pg_escape_string) to = zend_string_safe_alloc(ZSTR_LEN(from), 2, 0, 0); if (link) { + int err; pgsql = link->conn; - ZSTR_LEN(to) = PQescapeStringConn(pgsql, ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from), NULL); + ZSTR_LEN(to) = PQescapeStringConn(pgsql, ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from), &err); + if (err) { + zend_argument_value_error(ZEND_NUM_ARGS(), "Escaping string failed"); + zend_string_efree(to); + RETURN_THROWS(); + } } else { ZSTR_LEN(to) = PQescapeString(ZSTR_VAL(to), ZSTR_VAL(from), ZSTR_LEN(from)); @@ -3619,6 +3634,10 @@ PHP_FUNCTION(pg_escape_bytea) } else { to = (char *)PQescapeBytea((unsigned char *)ZSTR_VAL(from), ZSTR_LEN(from), &to_len); } + if (to == NULL) { + zend_argument_value_error(ZEND_NUM_ARGS(), "Escape failure"); + RETURN_THROWS(); + } RETVAL_STRINGL(to, to_len-1); /* to_len includes additional '\0' */ PQfreemem(to); @@ -4572,7 +4591,7 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string char *escaped; smart_str querystr = {0}; size_t new_len, len; - int i, num_rows; + int i, num_rows, err; zval elem; ZEND_ASSERT(ZSTR_LEN(table_name) != 0); @@ -4611,7 +4630,14 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string } len = strlen(tmp_name2); escaped = (char *)safe_emalloc(len, 2, 1); - new_len = PQescapeStringConn(pg_link, escaped, tmp_name2, len, NULL); + new_len = PQescapeStringConn(pg_link, escaped, tmp_name2, len, &err); + if (err) { + php_error_docref(NULL, E_WARNING, "Escaping table name '%s' failed", ZSTR_VAL(table_name)); + efree(src); + efree(escaped); + smart_str_free(&querystr); + return FAILURE; + } if (new_len) { smart_str_appendl(&querystr, escaped, new_len); } @@ -4620,7 +4646,14 @@ PHP_PGSQL_API zend_result php_pgsql_meta_data(PGconn *pg_link, const zend_string smart_str_appends(&querystr, "' AND n.nspname = '"); len = strlen(tmp_name); escaped = (char *)safe_emalloc(len, 2, 1); - new_len = PQescapeStringConn(pg_link, escaped, tmp_name, len, NULL); + new_len = PQescapeStringConn(pg_link, escaped, tmp_name, len, &err); + if (err) { + php_error_docref(NULL, E_WARNING, "Escaping table namespace '%s' failed", ZSTR_VAL(table_name)); + efree(src); + efree(escaped); + smart_str_free(&querystr); + return FAILURE; + } if (new_len) { smart_str_appendl(&querystr, escaped, new_len); } @@ -4875,7 +4908,7 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * { zend_string *field = NULL; zval meta, *def, *type, *not_null, *has_default, *is_enum, *val, new_val; - int err = 0; + int err = 0, escape_err = 0; bool skip_field; php_pgsql_data_type data_type; @@ -5121,8 +5154,13 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * /* PostgreSQL ignores \0 */ str = zend_string_alloc(Z_STRLEN_P(val) * 2, 0); /* better to use PGSQLescapeLiteral since PGescapeStringConn does not handle special \ */ - ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str), Z_STRVAL_P(val), Z_STRLEN_P(val), NULL); - ZVAL_STR(&new_val, php_pgsql_add_quotes(str)); + ZSTR_LEN(str) = PQescapeStringConn(pg_link, ZSTR_VAL(str), + Z_STRVAL_P(val), Z_STRLEN_P(val), &escape_err); + if (escape_err) { + err = 1; + } else { + ZVAL_STR(&new_val, php_pgsql_add_quotes(str)); + } zend_string_release_ex(str, false); } break; @@ -5145,7 +5183,14 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * } PGSQL_CONV_CHECK_IGNORE(); if (err) { - zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); + if (escape_err) { + php_error_docref(NULL, E_NOTICE, + "String value escaping failed for PostgreSQL '%s' (%s)", + Z_STRVAL_P(type), ZSTR_VAL(field)); + } else { + zend_type_error("%s(): Field \"%s\" must be of type string|null, %s given", + get_active_function_name(), ZSTR_VAL(field), Z_STRVAL_P(type)); + } } break; @@ -5379,6 +5424,11 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * zend_string *tmp_zstr; tmp = PQescapeByteaConn(pg_link, (unsigned char *)Z_STRVAL_P(val), Z_STRLEN_P(val), &to_len); + if (tmp == NULL) { + php_error_docref(NULL, E_NOTICE, "Escaping value failed for %s field (%s)", Z_STRVAL_P(type), ZSTR_VAL(field)); + err = 1; + break; + } tmp_zstr = zend_string_init((char *)tmp, to_len - 1, false); /* PQescapeBytea's to_len includes additional '\0' */ PQfreemem(tmp); @@ -5455,6 +5505,12 @@ PHP_PGSQL_API zend_result php_pgsql_convert(PGconn *pg_link, const zend_string * zend_hash_update(Z_ARRVAL_P(result), field, &new_val); } else { char *escaped = PQescapeIdentifier(pg_link, ZSTR_VAL(field), ZSTR_LEN(field)); + if (escaped == NULL) { + /* This cannot fail because of invalid string but only due to failed memory allocation */ + php_error_docref(NULL, E_NOTICE, "Escaping field '%s' failed", ZSTR_VAL(field)); + err = 1; + break; + } add_assoc_zval(result, escaped, &new_val); PQfreemem(escaped); } @@ -5537,7 +5593,7 @@ static bool do_exec(smart_str *querystr, ExecStatusType expect, PGconn *pg_link, } /* }}} */ -static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const zend_string *table) /* {{{ */ +static inline zend_result build_tablename(smart_str *querystr, PGconn *pg_link, const zend_string *table) /* {{{ */ { /* schema.table should be "schema"."table" */ const char *dot = memchr(ZSTR_VAL(table), '.', ZSTR_LEN(table)); @@ -5547,6 +5603,10 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z smart_str_appendl(querystr, ZSTR_VAL(table), len); } else { char *escaped = PQescapeIdentifier(pg_link, ZSTR_VAL(table), len); + if (escaped == NULL) { + php_error_docref(NULL, E_NOTICE, "Failed to escape table name '%s'", ZSTR_VAL(table)); + return FAILURE; + } smart_str_appends(querystr, escaped); PQfreemem(escaped); } @@ -5559,11 +5619,17 @@ static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const z smart_str_appendl(querystr, after_dot, len); } else { char *escaped = PQescapeIdentifier(pg_link, after_dot, len); + if (escaped == NULL) { + php_error_docref(NULL, E_NOTICE, "Failed to escape table name '%s'", ZSTR_VAL(table)); + return FAILURE; + } smart_str_appendc(querystr, '.'); smart_str_appends(querystr, escaped); PQfreemem(escaped); } } + + return SUCCESS; } /* }}} */ @@ -5584,7 +5650,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t ZVAL_UNDEF(&converted); if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0) { smart_str_appends(&querystr, "INSERT INTO "); - build_tablename(&querystr, pg_link, table); + if (build_tablename(&querystr, pg_link, table) == FAILURE) { + goto cleanup; + } smart_str_appends(&querystr, " DEFAULT VALUES"); goto no_values; @@ -5600,7 +5668,9 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t } smart_str_appends(&querystr, "INSERT INTO "); - build_tablename(&querystr, pg_link, table); + if (build_tablename(&querystr, pg_link, table) == FAILURE) { + goto cleanup; + } smart_str_appends(&querystr, " ("); ZEND_HASH_FOREACH_STR_KEY(Z_ARRVAL_P(var_array), fld) { @@ -5610,6 +5680,10 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t } if (opt & PGSQL_DML_ESCAPE) { tmp = PQescapeIdentifier(pg_link, ZSTR_VAL(fld), ZSTR_LEN(fld) + 1); + if (tmp == NULL) { + php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s'", ZSTR_VAL(fld)); + goto cleanup; + } smart_str_appends(&querystr, tmp); PQfreemem(tmp); } else { @@ -5621,15 +5695,19 @@ PHP_PGSQL_API zend_result php_pgsql_insert(PGconn *pg_link, const zend_string *t smart_str_appends(&querystr, ") VALUES ("); /* make values string */ - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(var_array), val) { + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(var_array), fld, val) { /* we can avoid the key_type check here, because we tested it in the other loop */ switch (Z_TYPE_P(val)) { case IS_STRING: if (opt & PGSQL_DML_ESCAPE) { - size_t new_len; - char *tmp; - tmp = (char *)safe_emalloc(Z_STRLEN_P(val), 2, 1); - new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), NULL); + int error; + char *tmp = safe_emalloc(Z_STRLEN_P(val), 2, 1); + size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), &error); + if (error) { + php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s' value", ZSTR_VAL(fld)); + efree(tmp); + goto cleanup; + } smart_str_appendc(&querystr, '\''); smart_str_appendl(&querystr, tmp, new_len); smart_str_appendc(&querystr, '\''); @@ -5787,6 +5865,10 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr, } if (opt & PGSQL_DML_ESCAPE) { char *tmp = PQescapeIdentifier(pg_link, ZSTR_VAL(fld), ZSTR_LEN(fld) + 1); + if (tmp == NULL) { + php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s'", ZSTR_VAL(fld)); + return -1; + } smart_str_appends(querystr, tmp); PQfreemem(tmp); } else { @@ -5802,8 +5884,14 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr, switch (Z_TYPE_P(val)) { case IS_STRING: if (opt & PGSQL_DML_ESCAPE) { + int error; char *tmp = (char *)safe_emalloc(Z_STRLEN_P(val), 2, 1); - size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), NULL); + size_t new_len = PQescapeStringConn(pg_link, tmp, Z_STRVAL_P(val), Z_STRLEN_P(val), &error); + if (error) { + php_error_docref(NULL, E_NOTICE, "Failed to escape field '%s' value", ZSTR_VAL(fld)); + efree(tmp); + return -1; + } smart_str_appendc(querystr, '\''); smart_str_appendl(querystr, tmp, new_len); smart_str_appendc(querystr, '\''); @@ -5871,7 +5959,9 @@ PHP_PGSQL_API zend_result php_pgsql_update(PGconn *pg_link, const zend_string *t } smart_str_appends(&querystr, "UPDATE "); - build_tablename(&querystr, pg_link, table); + if (build_tablename(&querystr, pg_link, table) == FAILURE) { + goto cleanup; + } smart_str_appends(&querystr, " SET "); if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(var_array), 0, ",", 1, opt)) @@ -5977,7 +6067,9 @@ PHP_PGSQL_API zend_result php_pgsql_delete(PGconn *pg_link, const zend_string *t } smart_str_appends(&querystr, "DELETE FROM "); - build_tablename(&querystr, pg_link, table); + if (build_tablename(&querystr, pg_link, table) == FAILURE) { + goto cleanup; + } smart_str_appends(&querystr, " WHERE "); if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1, opt)) @@ -6121,7 +6213,9 @@ PHP_PGSQL_API zend_result php_pgsql_select(PGconn *pg_link, const zend_string *t } smart_str_appends(&querystr, "SELECT * FROM "); - build_tablename(&querystr, pg_link, table); + if (build_tablename(&querystr, pg_link, table) == FAILURE) { + goto cleanup; + } if (is_valid_ids_array) { smart_str_appends(&querystr, " WHERE "); @@ -6168,7 +6262,6 @@ PHP_FUNCTION(pg_select) PGconn *pg_link; zend_string *sql = NULL; - /* TODO Document result_type param on php.net (apparently it was added in PHP 7.1) */ ZEND_PARSE_PARAMETERS_START(2, 5) Z_PARAM_OBJECT_OF_CLASS(pgsql_link, pgsql_link_ce) Z_PARAM_PATH_STR(table) @@ -6304,7 +6397,7 @@ PHP_FUNCTION(pg_socket_poll) Z_PARAM_LONG(ts) ZEND_PARSE_PARAMETERS_END(); - if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void **)&socket, 0)) { + if (UNEXPECTED(php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void **)&socket, 0) == FAILURE)) { zend_argument_type_error(1, "invalid resource socket"); RETURN_THROWS(); } diff --git a/ext/pgsql/pgsql.stub.php b/ext/pgsql/pgsql.stub.php index 04e648eff8d50..f379d115f6d45 100644 --- a/ext/pgsql/pgsql.stub.php +++ b/ext/pgsql/pgsql.stub.php @@ -13,8 +13,8 @@ /** * @var string * @cvalue pgsql_libpq_version - * @deprecated */ + #[\Deprecated(since: '8.0', message: 'as it is the same as PGSQL_LIBPQ_VERSION')] const PGSQL_LIBPQ_VERSION_STR = UNKNOWN; /* For connection option */ diff --git a/ext/pgsql/pgsql_arginfo.h b/ext/pgsql/pgsql_arginfo.h index cb58645e5e9f5..2d9eec944356e 100644 --- a/ext/pgsql/pgsql_arginfo.h +++ b/ext/pgsql/pgsql_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3cf44ca06d11cad086829d3d04900ade3cacb88b */ + * Stub hash: 7c5c32d94c0ac05313d8b19915c6318b0678b75b */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_connect, 0, 1, PgSql\\Connection, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0) @@ -757,7 +757,7 @@ static const zend_function_entry ext_functions[] = { static void register_pgsql_symbols(int module_number) { REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION", pgsql_libpq_version, CONST_PERSISTENT); - REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION_STR", pgsql_libpq_version, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_PGSQL_LIBPQ_VERSION_STR = REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION_STR", pgsql_libpq_version, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("PGSQL_CONNECT_FORCE_NEW", PGSQL_CONNECT_FORCE_NEW, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PGSQL_CONNECT_ASYNC", PGSQL_CONNECT_ASYNC, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PGSQL_ASSOC", PGSQL_ASSOC, CONST_PERSISTENT); @@ -865,294 +865,181 @@ static void register_pgsql_symbols(int module_number) zend_attribute *attribute_Deprecated_func_pg_errormessage_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_errormessage", sizeof("pg_errormessage") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_errormessage_0_arg0; - zend_string *attribute_Deprecated_func_pg_errormessage_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_errormessage_0_arg0, attribute_Deprecated_func_pg_errormessage_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_errormessage_0->args[0].value, &attribute_Deprecated_func_pg_errormessage_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_errormessage_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_errormessage_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_errormessage_0_arg1; zend_string *attribute_Deprecated_func_pg_errormessage_0_arg1_str = zend_string_init("use pg_last_error() instead", strlen("use pg_last_error() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_errormessage_0_arg1, attribute_Deprecated_func_pg_errormessage_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_errormessage_0->args[1].value, &attribute_Deprecated_func_pg_errormessage_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_errormessage_0->args[1].value, attribute_Deprecated_func_pg_errormessage_0_arg1_str); attribute_Deprecated_func_pg_errormessage_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_numrows_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_numrows", sizeof("pg_numrows") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_numrows_0_arg0; - zend_string *attribute_Deprecated_func_pg_numrows_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_numrows_0_arg0, attribute_Deprecated_func_pg_numrows_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_numrows_0->args[0].value, &attribute_Deprecated_func_pg_numrows_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_numrows_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_numrows_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_numrows_0_arg1; zend_string *attribute_Deprecated_func_pg_numrows_0_arg1_str = zend_string_init("use pg_num_rows() instead", strlen("use pg_num_rows() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_numrows_0_arg1, attribute_Deprecated_func_pg_numrows_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_numrows_0->args[1].value, &attribute_Deprecated_func_pg_numrows_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_numrows_0->args[1].value, attribute_Deprecated_func_pg_numrows_0_arg1_str); attribute_Deprecated_func_pg_numrows_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_numfields_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_numfields", sizeof("pg_numfields") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_numfields_0_arg0; - zend_string *attribute_Deprecated_func_pg_numfields_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_numfields_0_arg0, attribute_Deprecated_func_pg_numfields_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_numfields_0->args[0].value, &attribute_Deprecated_func_pg_numfields_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_numfields_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_numfields_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_numfields_0_arg1; zend_string *attribute_Deprecated_func_pg_numfields_0_arg1_str = zend_string_init("use pg_num_fields() instead", strlen("use pg_num_fields() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_numfields_0_arg1, attribute_Deprecated_func_pg_numfields_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_numfields_0->args[1].value, &attribute_Deprecated_func_pg_numfields_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_numfields_0->args[1].value, attribute_Deprecated_func_pg_numfields_0_arg1_str); attribute_Deprecated_func_pg_numfields_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_cmdtuples_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_cmdtuples", sizeof("pg_cmdtuples") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_cmdtuples_0_arg0; - zend_string *attribute_Deprecated_func_pg_cmdtuples_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_cmdtuples_0_arg0, attribute_Deprecated_func_pg_cmdtuples_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_cmdtuples_0->args[0].value, &attribute_Deprecated_func_pg_cmdtuples_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_cmdtuples_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_cmdtuples_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_cmdtuples_0_arg1; zend_string *attribute_Deprecated_func_pg_cmdtuples_0_arg1_str = zend_string_init("use pg_affected_rows() instead", strlen("use pg_affected_rows() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_cmdtuples_0_arg1, attribute_Deprecated_func_pg_cmdtuples_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_cmdtuples_0->args[1].value, &attribute_Deprecated_func_pg_cmdtuples_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_cmdtuples_0->args[1].value, attribute_Deprecated_func_pg_cmdtuples_0_arg1_str); attribute_Deprecated_func_pg_cmdtuples_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_fieldname_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_fieldname", sizeof("pg_fieldname") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_fieldname_0_arg0; - zend_string *attribute_Deprecated_func_pg_fieldname_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldname_0_arg0, attribute_Deprecated_func_pg_fieldname_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldname_0->args[0].value, &attribute_Deprecated_func_pg_fieldname_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldname_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_fieldname_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_fieldname_0_arg1; zend_string *attribute_Deprecated_func_pg_fieldname_0_arg1_str = zend_string_init("use pg_field_name() instead", strlen("use pg_field_name() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldname_0_arg1, attribute_Deprecated_func_pg_fieldname_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldname_0->args[1].value, &attribute_Deprecated_func_pg_fieldname_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldname_0->args[1].value, attribute_Deprecated_func_pg_fieldname_0_arg1_str); attribute_Deprecated_func_pg_fieldname_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_fieldsize_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_fieldsize", sizeof("pg_fieldsize") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_fieldsize_0_arg0; - zend_string *attribute_Deprecated_func_pg_fieldsize_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldsize_0_arg0, attribute_Deprecated_func_pg_fieldsize_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldsize_0->args[0].value, &attribute_Deprecated_func_pg_fieldsize_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldsize_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_fieldsize_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_fieldsize_0_arg1; zend_string *attribute_Deprecated_func_pg_fieldsize_0_arg1_str = zend_string_init("use pg_field_size() instead", strlen("use pg_field_size() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldsize_0_arg1, attribute_Deprecated_func_pg_fieldsize_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldsize_0->args[1].value, &attribute_Deprecated_func_pg_fieldsize_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldsize_0->args[1].value, attribute_Deprecated_func_pg_fieldsize_0_arg1_str); attribute_Deprecated_func_pg_fieldsize_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_fieldtype_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_fieldtype", sizeof("pg_fieldtype") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_fieldtype_0_arg0; - zend_string *attribute_Deprecated_func_pg_fieldtype_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldtype_0_arg0, attribute_Deprecated_func_pg_fieldtype_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldtype_0->args[0].value, &attribute_Deprecated_func_pg_fieldtype_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldtype_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_fieldtype_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_fieldtype_0_arg1; zend_string *attribute_Deprecated_func_pg_fieldtype_0_arg1_str = zend_string_init("use pg_field_type() instead", strlen("use pg_field_type() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldtype_0_arg1, attribute_Deprecated_func_pg_fieldtype_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldtype_0->args[1].value, &attribute_Deprecated_func_pg_fieldtype_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldtype_0->args[1].value, attribute_Deprecated_func_pg_fieldtype_0_arg1_str); attribute_Deprecated_func_pg_fieldtype_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_fieldnum_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_fieldnum", sizeof("pg_fieldnum") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_fieldnum_0_arg0; - zend_string *attribute_Deprecated_func_pg_fieldnum_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldnum_0_arg0, attribute_Deprecated_func_pg_fieldnum_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldnum_0->args[0].value, &attribute_Deprecated_func_pg_fieldnum_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldnum_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_fieldnum_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_fieldnum_0_arg1; zend_string *attribute_Deprecated_func_pg_fieldnum_0_arg1_str = zend_string_init("use pg_field_num() instead", strlen("use pg_field_num() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldnum_0_arg1, attribute_Deprecated_func_pg_fieldnum_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldnum_0->args[1].value, &attribute_Deprecated_func_pg_fieldnum_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldnum_0->args[1].value, attribute_Deprecated_func_pg_fieldnum_0_arg1_str); attribute_Deprecated_func_pg_fieldnum_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_result_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_result", sizeof("pg_result") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_result_0_arg0; - zend_string *attribute_Deprecated_func_pg_result_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_result_0_arg0, attribute_Deprecated_func_pg_result_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_result_0->args[0].value, &attribute_Deprecated_func_pg_result_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_result_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_result_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_result_0_arg1; zend_string *attribute_Deprecated_func_pg_result_0_arg1_str = zend_string_init("use pg_fetch_result() instead", strlen("use pg_fetch_result() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_result_0_arg1, attribute_Deprecated_func_pg_result_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_result_0->args[1].value, &attribute_Deprecated_func_pg_result_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_result_0->args[1].value, attribute_Deprecated_func_pg_result_0_arg1_str); attribute_Deprecated_func_pg_result_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_fieldprtlen_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_fieldprtlen", sizeof("pg_fieldprtlen") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_fieldprtlen_0_arg0; - zend_string *attribute_Deprecated_func_pg_fieldprtlen_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldprtlen_0_arg0, attribute_Deprecated_func_pg_fieldprtlen_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldprtlen_0->args[0].value, &attribute_Deprecated_func_pg_fieldprtlen_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldprtlen_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_fieldprtlen_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_fieldprtlen_0_arg1; zend_string *attribute_Deprecated_func_pg_fieldprtlen_0_arg1_str = zend_string_init("use pg_field_prtlen() instead", strlen("use pg_field_prtlen() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldprtlen_0_arg1, attribute_Deprecated_func_pg_fieldprtlen_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldprtlen_0->args[1].value, &attribute_Deprecated_func_pg_fieldprtlen_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldprtlen_0->args[1].value, attribute_Deprecated_func_pg_fieldprtlen_0_arg1_str); attribute_Deprecated_func_pg_fieldprtlen_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_fieldisnull_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_fieldisnull", sizeof("pg_fieldisnull") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_fieldisnull_0_arg0; - zend_string *attribute_Deprecated_func_pg_fieldisnull_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldisnull_0_arg0, attribute_Deprecated_func_pg_fieldisnull_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldisnull_0->args[0].value, &attribute_Deprecated_func_pg_fieldisnull_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldisnull_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_fieldisnull_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_fieldisnull_0_arg1; zend_string *attribute_Deprecated_func_pg_fieldisnull_0_arg1_str = zend_string_init("use pg_field_is_null() instead", strlen("use pg_field_is_null() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_fieldisnull_0_arg1, attribute_Deprecated_func_pg_fieldisnull_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_fieldisnull_0->args[1].value, &attribute_Deprecated_func_pg_fieldisnull_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_fieldisnull_0->args[1].value, attribute_Deprecated_func_pg_fieldisnull_0_arg1_str); attribute_Deprecated_func_pg_fieldisnull_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_freeresult_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_freeresult", sizeof("pg_freeresult") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_freeresult_0_arg0; - zend_string *attribute_Deprecated_func_pg_freeresult_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_freeresult_0_arg0, attribute_Deprecated_func_pg_freeresult_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_freeresult_0->args[0].value, &attribute_Deprecated_func_pg_freeresult_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_freeresult_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_freeresult_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_freeresult_0_arg1; zend_string *attribute_Deprecated_func_pg_freeresult_0_arg1_str = zend_string_init("use pg_free_result() instead", strlen("use pg_free_result() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_freeresult_0_arg1, attribute_Deprecated_func_pg_freeresult_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_freeresult_0->args[1].value, &attribute_Deprecated_func_pg_freeresult_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_freeresult_0->args[1].value, attribute_Deprecated_func_pg_freeresult_0_arg1_str); attribute_Deprecated_func_pg_freeresult_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_getlastoid_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_getlastoid", sizeof("pg_getlastoid") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_getlastoid_0_arg0; - zend_string *attribute_Deprecated_func_pg_getlastoid_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_getlastoid_0_arg0, attribute_Deprecated_func_pg_getlastoid_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_getlastoid_0->args[0].value, &attribute_Deprecated_func_pg_getlastoid_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_getlastoid_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_getlastoid_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_getlastoid_0_arg1; zend_string *attribute_Deprecated_func_pg_getlastoid_0_arg1_str = zend_string_init("use pg_last_oid() instead", strlen("use pg_last_oid() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_getlastoid_0_arg1, attribute_Deprecated_func_pg_getlastoid_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_getlastoid_0->args[1].value, &attribute_Deprecated_func_pg_getlastoid_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_getlastoid_0->args[1].value, attribute_Deprecated_func_pg_getlastoid_0_arg1_str); attribute_Deprecated_func_pg_getlastoid_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_locreate_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_locreate", sizeof("pg_locreate") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_locreate_0_arg0; - zend_string *attribute_Deprecated_func_pg_locreate_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_locreate_0_arg0, attribute_Deprecated_func_pg_locreate_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_locreate_0->args[0].value, &attribute_Deprecated_func_pg_locreate_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_locreate_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_locreate_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_locreate_0_arg1; zend_string *attribute_Deprecated_func_pg_locreate_0_arg1_str = zend_string_init("use pg_lo_create() instead", strlen("use pg_lo_create() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_locreate_0_arg1, attribute_Deprecated_func_pg_locreate_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_locreate_0->args[1].value, &attribute_Deprecated_func_pg_locreate_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_locreate_0->args[1].value, attribute_Deprecated_func_pg_locreate_0_arg1_str); attribute_Deprecated_func_pg_locreate_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_lounlink_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_lounlink", sizeof("pg_lounlink") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_lounlink_0_arg0; - zend_string *attribute_Deprecated_func_pg_lounlink_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_lounlink_0_arg0, attribute_Deprecated_func_pg_lounlink_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_lounlink_0->args[0].value, &attribute_Deprecated_func_pg_lounlink_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_lounlink_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_lounlink_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_lounlink_0_arg1; zend_string *attribute_Deprecated_func_pg_lounlink_0_arg1_str = zend_string_init("use pg_lo_unlink() instead", strlen("use pg_lo_unlink() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_lounlink_0_arg1, attribute_Deprecated_func_pg_lounlink_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_lounlink_0->args[1].value, &attribute_Deprecated_func_pg_lounlink_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_lounlink_0->args[1].value, attribute_Deprecated_func_pg_lounlink_0_arg1_str); attribute_Deprecated_func_pg_lounlink_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_loopen_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_loopen", sizeof("pg_loopen") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_loopen_0_arg0; - zend_string *attribute_Deprecated_func_pg_loopen_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loopen_0_arg0, attribute_Deprecated_func_pg_loopen_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loopen_0->args[0].value, &attribute_Deprecated_func_pg_loopen_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_loopen_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_loopen_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_loopen_0_arg1; zend_string *attribute_Deprecated_func_pg_loopen_0_arg1_str = zend_string_init("use pg_lo_open() instead", strlen("use pg_lo_open() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loopen_0_arg1, attribute_Deprecated_func_pg_loopen_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loopen_0->args[1].value, &attribute_Deprecated_func_pg_loopen_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_loopen_0->args[1].value, attribute_Deprecated_func_pg_loopen_0_arg1_str); attribute_Deprecated_func_pg_loopen_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_loclose_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_loclose", sizeof("pg_loclose") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_loclose_0_arg0; - zend_string *attribute_Deprecated_func_pg_loclose_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loclose_0_arg0, attribute_Deprecated_func_pg_loclose_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loclose_0->args[0].value, &attribute_Deprecated_func_pg_loclose_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_loclose_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_loclose_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_loclose_0_arg1; zend_string *attribute_Deprecated_func_pg_loclose_0_arg1_str = zend_string_init("use pg_lo_close() instead", strlen("use pg_lo_close() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loclose_0_arg1, attribute_Deprecated_func_pg_loclose_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loclose_0->args[1].value, &attribute_Deprecated_func_pg_loclose_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_loclose_0->args[1].value, attribute_Deprecated_func_pg_loclose_0_arg1_str); attribute_Deprecated_func_pg_loclose_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_loread_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_loread", sizeof("pg_loread") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_loread_0_arg0; - zend_string *attribute_Deprecated_func_pg_loread_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loread_0_arg0, attribute_Deprecated_func_pg_loread_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loread_0->args[0].value, &attribute_Deprecated_func_pg_loread_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_loread_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_loread_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_loread_0_arg1; zend_string *attribute_Deprecated_func_pg_loread_0_arg1_str = zend_string_init("use pg_lo_read() instead", strlen("use pg_lo_read() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loread_0_arg1, attribute_Deprecated_func_pg_loread_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loread_0->args[1].value, &attribute_Deprecated_func_pg_loread_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_loread_0->args[1].value, attribute_Deprecated_func_pg_loread_0_arg1_str); attribute_Deprecated_func_pg_loread_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_lowrite_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_lowrite", sizeof("pg_lowrite") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_lowrite_0_arg0; - zend_string *attribute_Deprecated_func_pg_lowrite_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_lowrite_0_arg0, attribute_Deprecated_func_pg_lowrite_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_lowrite_0->args[0].value, &attribute_Deprecated_func_pg_lowrite_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_lowrite_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_lowrite_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_lowrite_0_arg1; zend_string *attribute_Deprecated_func_pg_lowrite_0_arg1_str = zend_string_init("use pg_lo_write() instead", strlen("use pg_lo_write() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_lowrite_0_arg1, attribute_Deprecated_func_pg_lowrite_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_lowrite_0->args[1].value, &attribute_Deprecated_func_pg_lowrite_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_lowrite_0->args[1].value, attribute_Deprecated_func_pg_lowrite_0_arg1_str); attribute_Deprecated_func_pg_lowrite_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_loreadall_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_loreadall", sizeof("pg_loreadall") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_loreadall_0_arg0; - zend_string *attribute_Deprecated_func_pg_loreadall_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loreadall_0_arg0, attribute_Deprecated_func_pg_loreadall_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loreadall_0->args[0].value, &attribute_Deprecated_func_pg_loreadall_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_loreadall_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_loreadall_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_loreadall_0_arg1; zend_string *attribute_Deprecated_func_pg_loreadall_0_arg1_str = zend_string_init("use pg_lo_read_all() instead", strlen("use pg_lo_read_all() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loreadall_0_arg1, attribute_Deprecated_func_pg_loreadall_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loreadall_0->args[1].value, &attribute_Deprecated_func_pg_loreadall_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_loreadall_0->args[1].value, attribute_Deprecated_func_pg_loreadall_0_arg1_str); attribute_Deprecated_func_pg_loreadall_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_loimport_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_loimport", sizeof("pg_loimport") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_loimport_0_arg0; - zend_string *attribute_Deprecated_func_pg_loimport_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loimport_0_arg0, attribute_Deprecated_func_pg_loimport_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loimport_0->args[0].value, &attribute_Deprecated_func_pg_loimport_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_loimport_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_loimport_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_loimport_0_arg1; zend_string *attribute_Deprecated_func_pg_loimport_0_arg1_str = zend_string_init("use pg_lo_import() instead", strlen("use pg_lo_import() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loimport_0_arg1, attribute_Deprecated_func_pg_loimport_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loimport_0->args[1].value, &attribute_Deprecated_func_pg_loimport_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_loimport_0->args[1].value, attribute_Deprecated_func_pg_loimport_0_arg1_str); attribute_Deprecated_func_pg_loimport_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_loexport_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_loexport", sizeof("pg_loexport") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_loexport_0_arg0; - zend_string *attribute_Deprecated_func_pg_loexport_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loexport_0_arg0, attribute_Deprecated_func_pg_loexport_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loexport_0->args[0].value, &attribute_Deprecated_func_pg_loexport_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_loexport_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_loexport_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_loexport_0_arg1; zend_string *attribute_Deprecated_func_pg_loexport_0_arg1_str = zend_string_init("use pg_lo_export() instead", strlen("use pg_lo_export() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_loexport_0_arg1, attribute_Deprecated_func_pg_loexport_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_loexport_0->args[1].value, &attribute_Deprecated_func_pg_loexport_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_loexport_0->args[1].value, attribute_Deprecated_func_pg_loexport_0_arg1_str); attribute_Deprecated_func_pg_loexport_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_setclientencoding_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_setclientencoding", sizeof("pg_setclientencoding") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_setclientencoding_0_arg0; - zend_string *attribute_Deprecated_func_pg_setclientencoding_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_setclientencoding_0_arg0, attribute_Deprecated_func_pg_setclientencoding_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_setclientencoding_0->args[0].value, &attribute_Deprecated_func_pg_setclientencoding_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_setclientencoding_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_setclientencoding_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_setclientencoding_0_arg1; zend_string *attribute_Deprecated_func_pg_setclientencoding_0_arg1_str = zend_string_init("use pg_set_client_encoding() instead", strlen("use pg_set_client_encoding() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_setclientencoding_0_arg1, attribute_Deprecated_func_pg_setclientencoding_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_setclientencoding_0->args[1].value, &attribute_Deprecated_func_pg_setclientencoding_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_setclientencoding_0->args[1].value, attribute_Deprecated_func_pg_setclientencoding_0_arg1_str); attribute_Deprecated_func_pg_setclientencoding_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_pg_clientencoding_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_clientencoding", sizeof("pg_clientencoding") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_pg_clientencoding_0_arg0; - zend_string *attribute_Deprecated_func_pg_clientencoding_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_clientencoding_0_arg0, attribute_Deprecated_func_pg_clientencoding_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_clientencoding_0->args[0].value, &attribute_Deprecated_func_pg_clientencoding_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_pg_clientencoding_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_pg_clientencoding_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_pg_clientencoding_0_arg1; zend_string *attribute_Deprecated_func_pg_clientencoding_0_arg1_str = zend_string_init("use pg_client_encoding() instead", strlen("use pg_client_encoding() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_pg_clientencoding_0_arg1, attribute_Deprecated_func_pg_clientencoding_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_pg_clientencoding_0->args[1].value, &attribute_Deprecated_func_pg_clientencoding_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_pg_clientencoding_0->args[1].value, attribute_Deprecated_func_pg_clientencoding_0_arg1_str); attribute_Deprecated_func_pg_clientencoding_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "pg_change_password", sizeof("pg_change_password") - 1), 2, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); + + zend_attribute *attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0 = zend_add_global_constant_attribute(const_PGSQL_LIBPQ_VERSION_STR, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); + attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0_arg1_str = zend_string_init("as it is the same as PGSQL_LIBPQ_VERSION", strlen("as it is the same as PGSQL_LIBPQ_VERSION"), 1); + ZVAL_STR(&attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0->args[1].value, attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0_arg1_str); + attribute_Deprecated_const_PGSQL_LIBPQ_VERSION_STR_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_PgSql_Connection(void) diff --git a/ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt b/ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt new file mode 100644 index 0000000000000..6cbfe6d1f5859 --- /dev/null +++ b/ext/pgsql/tests/ghsa-hrwm-9436-5mv3.phpt @@ -0,0 +1,64 @@ +--TEST-- +#GHSA-hrwm-9436-5mv3: pgsql extension does not check for errors during escaping +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- + 'test'])); // table name str escape in php_pgsql_meta_data +var_dump(pg_insert($db, "$invalid.tbl", ['bar' => 'test'])); // schema name str escape in php_pgsql_meta_data +var_dump(pg_insert($db, 'ghsa_hrmw_9436_5mv3', ['bar' => $invalid])); // converted value str escape in php_pgsql_convert +var_dump(pg_insert($db, $invalid, [])); // ident escape in build_tablename +var_dump(pg_insert($db, 'ghsa_hrmw_9436_5mv3', [$invalid => 'foo'], $flags)); // ident escape for field php_pgsql_insert +var_dump(pg_insert($db, 'ghsa_hrmw_9436_5mv3', ['bar' => $invalid], $flags)); // str escape for field value in php_pgsql_insert +var_dump(pg_update($db, 'ghsa_hrmw_9436_5mv3', ['bar' => 'val'], [$invalid => 'test'], $flags)); // ident escape in build_assignment_string +var_dump(pg_update($db, 'ghsa_hrmw_9436_5mv3', ['bar' => 'val'], ['bar' => $invalid], $flags)); // invalid str escape in build_assignment_string +var_dump(pg_escape_literal($db, $invalid)); // pg_escape_literal escape +var_dump(pg_escape_identifier($db, $invalid)); // pg_escape_identifier escape + +?> +--EXPECTF-- + +Warning: pg_insert(): Escaping table name 'ABC%s';' failed in %s on line %d +bool(false) + +Warning: pg_insert(): Escaping table namespace 'ABC%s';.tbl' failed in %s on line %d +bool(false) + +Notice: pg_insert(): String value escaping failed for PostgreSQL 'text' (bar) in %s on line %d +bool(false) + +Notice: pg_insert(): Failed to escape table name 'ABC%s';' in %s on line %d +bool(false) + +Notice: pg_insert(): Failed to escape field 'ABC%s';' in %s on line %d +bool(false) + +Notice: pg_insert(): Failed to escape field 'bar' value in %s on line %d +bool(false) + +Notice: pg_update(): Failed to escape field 'ABC%s';' in %s on line %d +bool(false) + +Notice: pg_update(): Failed to escape field 'bar' value in %s on line %d +bool(false) + +Warning: pg_escape_literal(): Failed to escape in %s on line %d +bool(false) + +Warning: pg_escape_identifier(): Failed to escape in %s on line %d +bool(false) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index de3b1b4ee199e..76a580988fb62 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2708,7 +2708,7 @@ void phar_flush_ex(phar_archive_data *phar, zend_string *user_stub, bool is_defa /* remove this from the new phar */ continue; } - if (!entry->is_modified && entry->fp_refcount) { + if (entry->fp_refcount) { /* open file pointers refer to this fp, do not free the stream */ switch (entry->fp_type) { case PHAR_FP: diff --git a/ext/phar/phar/pharcommand.inc b/ext/phar/phar/pharcommand.inc index fee6c069ab085..7d35335a29470 100644 --- a/ext/phar/phar/pharcommand.inc +++ b/ext/phar/phar/pharcommand.inc @@ -225,13 +225,13 @@ class PharCommand extends CLICommand } } if ($pear) { - $apiver = (string) `pear -q info PHP_Archive 2>/dev/null|grep 'API Version'`; + $apiver = (string) shell_exec("pear -q info PHP_Archive 2>/dev/null|grep 'API Version'"); $apiver = trim(substr($apiver, strlen('API Version'))); } if ($apiver) { self::notice("PEAR package PHP_Archive: API Version: $apiver.\n"); - $files = explode("\n", (string) `pear list-files PHP_Archive`); - $phpdir = (string) `pear config-get php_dir 2>/dev/null`; + $files = explode("\n", (string) shell_exec("pear list-files PHP_Archive")); + $phpdir = (string) shell_exec("pear config-get php_dir 2>/dev/null"); $phpdir = trim($phpdir); self::notice("PEAR package PHP_Archive: $phpdir.\n"); if (is_dir($phpdir)) { diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 723339a431ee2..e584338b23e74 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1934,7 +1934,8 @@ static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *f { char *error; zend_off_t offset; - phar_entry_info *link; + + ZEND_ASSERT(!entry->link); if (FAILURE == phar_open_entry_fp(entry, &error, 1)) { if (error) { @@ -1949,26 +1950,14 @@ static zend_result phar_copy_file_contents(phar_entry_info *entry, php_stream *f } /* copy old contents in entirety */ - phar_seek_efp(entry, 0, SEEK_SET, 0, 1); + phar_seek_efp(entry, 0, SEEK_SET, 0, 0); offset = php_stream_tell(fp); - link = phar_get_link_source(entry); - - if (!link) { - link = entry; - } - - if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) { + if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, ZSTR_VAL(entry->filename)); return FAILURE; } - if (entry->fp_type == PHAR_MOD) { - /* save for potential restore on error */ - entry->cfp = entry->fp; - entry->fp = NULL; - } - /* set new location of file contents */ entry->fp_type = PHAR_FP; entry->offset = offset; @@ -2248,6 +2237,12 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert PHAR_G(last_phar) = NULL; PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL; + php_stream *tmp_fp = php_stream_fopen_tmpfile(); + if (tmp_fp == NULL) { + zend_throw_exception_ex(phar_ce_PharException, 0, "unable to create temporary file"); + return NULL; + } + phar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data)); /* set whole-archive compression and type from parameter */ phar->flags = flags; @@ -2272,11 +2267,7 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert zend_hash_init(&phar->virtual_dirs, sizeof(char *), zend_get_hash_value, NULL, 0); - phar->fp = php_stream_fopen_tmpfile(); - if (phar->fp == NULL) { - zend_throw_exception_ex(phar_ce_PharException, 0, "unable to create temporary file"); - return NULL; - } + phar->fp = tmp_fp; phar->fname = source->fname; phar->fname_len = source->fname_len; phar->is_temporary_alias = source->is_temporary_alias; @@ -2300,6 +2291,7 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert } if (FAILURE == phar_copy_file_contents(&newentry, phar->fp)) { + phar_metadata_tracker_free(&phar->metadata_tracker, phar->is_persistent); zend_hash_destroy(&(phar->manifest)); php_stream_close(phar->fp); efree(phar); @@ -2307,6 +2299,10 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert return NULL; } no_copy: + /* Reset file pointers, they have to be reset here such that if a copy happens the original + * source fp can be accessed. */ + newentry.fp = NULL; + newentry.cfp = NULL; newentry.filename = zend_string_copy(newentry.filename); phar_metadata_tracker_clone(&newentry.metadata_tracker); @@ -2333,13 +2329,18 @@ static zend_object *phar_convert_to_other(phar_archive_data *source, int convert return ret; } else { if(phar != NULL) { + phar_metadata_tracker_free(&phar->metadata_tracker, phar->is_persistent); zend_hash_destroy(&(phar->manifest)); zend_hash_destroy(&(phar->mounted_dirs)); zend_hash_destroy(&(phar->virtual_dirs)); if (phar->fp) { php_stream_close(phar->fp); } - efree(phar->fname); + if (phar->fname != source->fname) { + /* Depending on when phar_rename_archive() errors, the new filename + * may have already been assigned or it may still be the old one. */ + efree(phar->fname); + } efree(phar); } return NULL; diff --git a/ext/phar/shortarc.php b/ext/phar/shortarc.php index 2d0d37d0dcc56..0e88198a87a4f 100644 --- a/ext/phar/shortarc.php +++ b/ext/phar/shortarc.php @@ -114,15 +114,15 @@ static function go($return = false) { $fp = fopen(__FILE__, 'rb'); fseek($fp, self::LEN); - $L = unpack('V', $a = (binary)fread($fp, 4)); - $m = (binary)''; + $L = unpack('V', $a = (string)fread($fp, 4)); + $m = ''; do { $read = 8192; if ($L[1] - strlen($m) < 8192) { $read = $L[1] - strlen($m); } - $last = (binary)fread($fp, $read); + $last = (string)fread($fp, $read); $m .= $last; } while (strlen($last) && strlen($m) < $L[1]); @@ -268,7 +268,7 @@ static function extractFile($path, $entry, $fp) $entry[0] . ")"); } - if ($entry[3] != sprintf("%u", crc32((binary)$data) & 0xffffffff)) { + if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { die("Invalid internal .phar file (checksum error)"); } diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 38c0c3e6f8010..2ac8e79c4c0bd 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -445,12 +445,12 @@ static ssize_t phar_stream_write(php_stream *stream, const char *buf, size_t cou { phar_entry_data *data = (phar_entry_data *) stream->abstract; - php_stream_seek(data->fp, data->position, SEEK_SET); + php_stream_seek(data->fp, data->position + data->zero, SEEK_SET); if (count != php_stream_write(data->fp, buf, count)) { php_stream_wrapper_log_error(stream->wrapper, stream->flags, "phar error: Could not write %d characters to \"%s\" in phar \"%s\"", (int) count, ZSTR_VAL(data->internal_file->filename), data->phar->fname); return -1; } - data->position = php_stream_tell(data->fp); + data->position = php_stream_tell(data->fp) - data->zero; if (data->position > (zend_off_t)data->internal_file->uncompressed_filesize) { data->internal_file->uncompressed_filesize = data->position; } diff --git a/ext/phar/tar.c b/ext/phar/tar.c index a91419d84c779..0f90104014c04 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -841,7 +841,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* php_stream_write(fp->new, padding, ((entry->uncompressed_filesize +511)&~511) - entry->uncompressed_filesize); } - if (!entry->is_modified && entry->fp_refcount) { + if (entry->fp_refcount) { /* open file pointers refer to this fp, do not free the stream */ switch (entry->fp_type) { case PHAR_FP: @@ -1170,6 +1170,7 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def } zend_hash_apply_with_argument(&phar->manifest, phar_tar_writeheaders, (void *) &pass); + /* TODO: memory leak and incorrect continuation if phar_tar_writeheaders fails? */ /* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */ if (!phar->is_data || phar->sig_flags) { @@ -1191,6 +1192,12 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def entry.fp = php_stream_fopen_tmpfile(); if (entry.fp == NULL) { spprintf(error, 0, "phar error: unable to create temporary file"); + + efree(signature); + if (must_close_old_file) { + php_stream_close(oldfile); + } + php_stream_close(newfile); return; } #ifdef WORDS_BIGENDIAN diff --git a/ext/phar/tests/bug77432.phpt b/ext/phar/tests/bug77432.phpt index b3b927a5439df..86a07fe99a4e9 100644 --- a/ext/phar/tests/bug77432.phpt +++ b/ext/phar/tests/bug77432.phpt @@ -21,8 +21,6 @@ unset($phar); echo "--- Include 1 ---\n"; include("phar://" . $filename); echo "--- Include 2 ---\n"; -// Note: will warn because the halting offset is redefined, but won't display the name because "zend_mangle_property_name" starts the name with \0 -// However, this is just the easiest way to reproduce it, so go with this test. include("phar://" . $filename); echo "--- After unlink ---\n"; unlink($filename); @@ -38,8 +36,6 @@ include("phar://" . $filename); --- Include 1 --- hello world --- Include 2 --- - -Warning: Constant already defined in %s on line %d hello world --- After unlink --- diff --git a/ext/phar/tests/cache_list/files/phar_test.inc b/ext/phar/tests/cache_list/files/phar_test.inc index bae9415aac4a3..b30b2f2fce39d 100644 --- a/ext/phar/tests/cache_list/files/phar_test.inc +++ b/ext/phar/tests/cache_list/files/phar_test.inc @@ -2,7 +2,7 @@ date_default_timezone_set('UTC'); -$manifest = (binary)''; +$manifest = ''; $glags = 0; foreach($files as $name => $cont) @@ -34,12 +34,12 @@ foreach($files as $name => $cont) if (empty($comp)) $comp = $cont; if (empty($ulen)) $ulen = strlen($cont); if (empty($clen)) $clen = strlen($comp); - if (empty($crc32))$crc32= crc32((binary)$cont); + if (empty($crc32))$crc32= crc32($cont); if (isset($meta)) $meta = serialize($meta); // write manifest entry - $manifest .= pack('V', strlen($name)) . (binary)$name; - $manifest .= pack('VVVVVV', $ulen, $time, $clen, $crc32, $flags|$perm, strlen($meta)) . (binary)$meta; + $manifest .= pack('V', strlen($name)) . $name; + $manifest .= pack('VVVVVV', $ulen, $time, $clen, $crc32, $flags|$perm, strlen($meta)) . $meta; // globals $gflags |= $flags; @@ -50,13 +50,13 @@ if (!isset($alias)) $alias = 'hio'; if (isset($pmeta)) $pmeta = serialize($pmeta); else $pmeta = ''; -$manifest = pack('VnVV', count($files), isset($hasdir) ? 0x1110 : 0x1000, $gflags, strlen($alias)) . (binary)$alias . pack('V', strlen($pmeta)) . (binary)$pmeta . $manifest; -$file = (binary)$file; +$manifest = pack('VnVV', count($files), isset($hasdir) ? 0x1110 : 0x1000, $gflags, strlen($alias)) . $alias . pack('V', strlen($pmeta)) . $pmeta . $manifest; +$file = $file; $file .= pack('V', strlen($manifest)) . $manifest; foreach($files as $cont) { - $file .= (binary)$cont; + $file .= $cont; } file_put_contents($fname, $file); diff --git a/ext/phar/tests/files/phar_oo_test.inc b/ext/phar/tests/files/phar_oo_test.inc index a6f4cee5ee657..b935346bc8efd 100644 --- a/ext/phar/tests/files/phar_oo_test.inc +++ b/ext/phar/tests/files/phar_oo_test.inc @@ -5,7 +5,7 @@ ini_set('date.timezone', 'GMT'); $tname = basename(current(get_included_files()), ".php"); $fname = dirname(__FILE__) . "/$tname.phar.php"; $pname = 'phar://' . $fname; -$file = (binary)''; +$file = ''; $files = array(); diff --git a/ext/phar/tests/files/phar_test.inc b/ext/phar/tests/files/phar_test.inc index 277271ef4c63b..caf220d0b37b8 100644 --- a/ext/phar/tests/files/phar_test.inc +++ b/ext/phar/tests/files/phar_test.inc @@ -2,7 +2,7 @@ date_default_timezone_set('UTC'); -$manifest = (binary)''; +$manifest = ''; $gflags = 0; foreach($files as $name => $cont) @@ -34,12 +34,12 @@ foreach($files as $name => $cont) if (empty($comp)) $comp = $cont; if (empty($ulen)) $ulen = strlen($cont); if (empty($clen)) $clen = strlen($comp); - if (empty($crc32))$crc32= crc32((binary)$cont); + if (empty($crc32))$crc32= crc32($cont); $meta = isset($meta) ? serialize($meta) : ""; // write manifest entry - $manifest .= pack('V', strlen($name)) . (binary)$name; - $manifest .= pack('VVVVVV', $ulen, $time, $clen, $crc32, $flags|$perm, strlen($meta)) . (binary)$meta; + $manifest .= pack('V', strlen($name)) . $name; + $manifest .= pack('VVVVVV', $ulen, $time, $clen, $crc32, $flags|$perm, strlen($meta)) . $meta; // globals $gflags |= $flags; @@ -50,13 +50,13 @@ if (!isset($alias)) $alias = 'hio'; if (isset($pmeta)) $pmeta = serialize($pmeta); else $pmeta = ''; -$manifest = pack('VnVV', count($files), isset($hasdir) ? 0x1110 : 0x1000, $gflags, strlen($alias)) . (binary)$alias . pack('V', strlen($pmeta)) . (binary)$pmeta . $manifest; -$file = (binary)$file; +$manifest = pack('VnVV', count($files), isset($hasdir) ? 0x1110 : 0x1000, $gflags, strlen($alias)) . $alias . pack('V', strlen($pmeta)) . $pmeta . $manifest; +$file = $file; $file .= pack('V', strlen($manifest)) . $manifest; foreach($files as $cont) { - $file .= (binary)$cont; + $file .= $cont; } file_put_contents($fname, $file); diff --git a/ext/phar/tests/gh18953.phpt b/ext/phar/tests/gh18953.phpt new file mode 100644 index 0000000000000..ff48e457cc9fb --- /dev/null +++ b/ext/phar/tests/gh18953.phpt @@ -0,0 +1,41 @@ +--TEST-- +GH-18953 (Phar: Stream double free) +--EXTENSIONS-- +phar +zlib +--INI-- +phar.readonly=0 +--FILE-- +addFromString("file", str_repeat("123", random_int(1, 1))); +$phar->addEmptyDir("dir"); +$phar2 = $phar->compress(Phar::GZ); + +var_dump($phar["dir"]); +var_dump($phar2["dir"]); +var_dump($phar["file"]->openFile()->fread(100)); +var_dump($phar2["file"]->openFile()->fread(100)); + +?> +--CLEAN-- + +--EXPECTF-- +object(PharFileInfo)#%d (2) { + ["pathName":"SplFileInfo":private]=> + string(%d) "%sphar%sdir" + ["fileName":"SplFileInfo":private]=> + string(3) "dir" +} +object(PharFileInfo)#%d (2) { + ["pathName":"SplFileInfo":private]=> + string(%d) "%sphar.gz%sdir" + ["fileName":"SplFileInfo":private]=> + string(3) "dir" +} +string(3) "123" +string(3) "123" diff --git a/ext/phar/tests/gh19038.phpt b/ext/phar/tests/gh19038.phpt new file mode 100644 index 0000000000000..34eba44c1dcd6 --- /dev/null +++ b/ext/phar/tests/gh19038.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19038 (Phar crash and data corruption with SplFileObject) +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +--FILE-- +addFromString("file", "123"); +$file = $phar["file"]->openFile(); +$file->fseek(3); +var_dump($file->fwrite("456", 3)); +$file->fseek(0); +echo $file->fread(100); + +?> +--CLEAN-- + +--EXPECT-- +int(3) +123456 diff --git a/ext/phar/tests/gh19752.phpt b/ext/phar/tests/gh19752.phpt new file mode 100644 index 0000000000000..94ee8691305e9 --- /dev/null +++ b/ext/phar/tests/gh19752.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-19752 (Phar decompression with invalid extension can cause UAF) +--EXTENSIONS-- +phar +--FILE-- +decompress("*"); +} catch (BadMethodCallException $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECTF-- +data phar converted from "%sgh19752.1" has invalid extension * diff --git a/ext/phar/tests/phar_convert_metadata_leak.phpt b/ext/phar/tests/phar_convert_metadata_leak.phpt new file mode 100644 index 0000000000000..61a240c8888da --- /dev/null +++ b/ext/phar/tests/phar_convert_metadata_leak.phpt @@ -0,0 +1,24 @@ +--TEST-- +Phar convert logic leaks metadata +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- +setMetadata("foobar"); +$phar['x'] = 'hi'; +try { + $phar->convertToData(Phar::ZIP, Phar::NONE, 'phar.zip'); +} catch (BadMethodCallException $e) { + echo $e->getMessage(),"\n"; +} +?> +--CLEAN-- + +--EXPECTF-- +data phar "%s" has invalid extension phar.zip diff --git a/ext/phar/tests/phar_metadata_write3.phpt b/ext/phar/tests/phar_metadata_write3.phpt index 304ed65b46e9f..bc3c5c45fe2f0 100644 --- a/ext/phar/tests/phar_metadata_write3.phpt +++ b/ext/phar/tests/phar_metadata_write3.phpt @@ -58,6 +58,7 @@ unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.phar.php.copy.php'); ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d Reading file contents through stream wrapper string(18) "contents of file a" Original metadata diff --git a/ext/phar/tests/phar_metadata_write4.phpt b/ext/phar/tests/phar_metadata_write4.phpt index ad9f4d47d91c6..1d552ba284880 100644 --- a/ext/phar/tests/phar_metadata_write4.phpt +++ b/ext/phar/tests/phar_metadata_write4.phpt @@ -68,6 +68,9 @@ unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.phar.php.copy.php'); ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d In __destruct 1 string(1) "a" Loading metadata for 'a' without allowed_classes diff --git a/ext/phar/tests/tar/files/make.dangerous.tar.php.inc b/ext/phar/tests/tar/files/make.dangerous.tar.php.inc index 641dda56f595f..ff9c20ccf9b7d 100644 --- a/ext/phar/tests/tar/files/make.dangerous.tar.php.inc +++ b/ext/phar/tests/tar/files/make.dangerous.tar.php.inc @@ -108,16 +108,16 @@ class danger_tarmaker $checksum = pack('a8', sprintf('%6s ', decoct($checksum))); - fwrite($this->tmp, (binary)$block . $checksum . $blockend, 512); + fwrite($this->tmp, $block . $checksum . $blockend, 512); if (is_resource($fileOrStream)) { stream_copy_to_stream($fileOrStream, $this->tmp); if ($stat['size'] % 512) { - fwrite($this->tmp, (binary)str_repeat("\0", 512 - $stat['size'] % 512)); + fwrite($this->tmp, str_repeat("\0", 512 - $stat['size'] % 512)); } } else { - fwrite($this->tmp, (binary)$fileOrStream); + fwrite($this->tmp, $fileOrStream); if (strlen($fileOrStream) % 512) { - fwrite($this->tmp, (binary)str_repeat("\0", 512 - strlen($fileOrStream) % 512)); + fwrite($this->tmp, str_repeat("\0", 512 - strlen($fileOrStream) % 512)); } } } diff --git a/ext/phar/tests/tar/files/make_invalid_tar.php.inc b/ext/phar/tests/tar/files/make_invalid_tar.php.inc index 2ccdf00201c02..cf9034bc30769 100644 --- a/ext/phar/tests/tar/files/make_invalid_tar.php.inc +++ b/ext/phar/tests/tar/files/make_invalid_tar.php.inc @@ -3,7 +3,7 @@ include dirname(__FILE__) . '/tarmaker.php.inc'; class corrupter extends tarmaker { function close() { - fwrite($this->tmp, (binary)'oopsie'); + fwrite($this->tmp, 'oopsie'); fclose($this->tmp); } } diff --git a/ext/phar/tests/tar/files/tarmaker.php.inc b/ext/phar/tests/tar/files/tarmaker.php.inc index 5860bf84d314f..ce0bd249b51df 100644 --- a/ext/phar/tests/tar/files/tarmaker.php.inc +++ b/ext/phar/tests/tar/files/tarmaker.php.inc @@ -107,16 +107,16 @@ class tarmaker $checksum = pack('a8', sprintf('%6s ', decoct($checksum))); - fwrite($this->tmp, (binary)$block . $checksum . $blockend, 512); + fwrite($this->tmp, $block . $checksum . $blockend, 512); if (is_resource($fileOrStream)) { stream_copy_to_stream($fileOrStream, $this->tmp); if ($stat['size'] % 512) { - fwrite($this->tmp, (binary)str_repeat("\0", 512 - $stat['size'] % 512)); + fwrite($this->tmp, str_repeat("\0", 512 - $stat['size'] % 512)); } } else { - fwrite($this->tmp, (binary)$fileOrStream); + fwrite($this->tmp, $fileOrStream); if (strlen($fileOrStream) % 512) { - fwrite($this->tmp, (binary)str_repeat("\0", 512 - strlen($fileOrStream) % 512)); + fwrite($this->tmp, str_repeat("\0", 512 - strlen($fileOrStream) % 512)); } } } diff --git a/ext/phar/util.c b/ext/phar/util.c index 06394813574b7..aa30515eff6a0 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1921,6 +1921,7 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char if (!EVP_SignInit(md_ctx, mdtype)) { EVP_PKEY_free(key); + EVP_MD_CTX_free(md_ctx); efree(sigbuf); if (error) { spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname); @@ -1931,6 +1932,7 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) { if (!EVP_SignUpdate(md_ctx, buf, sig_len)) { EVP_PKEY_free(key); + EVP_MD_CTX_free(md_ctx); efree(sigbuf); if (error) { spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", phar->fname); @@ -1941,6 +1943,7 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char if (!EVP_SignFinal (md_ctx, sigbuf, &siglen, key)) { EVP_PKEY_free(key); + EVP_MD_CTX_free(md_ctx); efree(sigbuf); if (error) { spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname); @@ -1950,7 +1953,7 @@ zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char sigbuf[siglen] = '\0'; EVP_PKEY_free(key); - EVP_MD_CTX_destroy(md_ctx); + EVP_MD_CTX_free(md_ctx); #else size_t siglen; sigbuf = NULL; diff --git a/ext/posix/config.m4 b/ext/posix/config.m4 index b7a6e4277251e..8960979065f98 100644 --- a/ext/posix/config.m4 +++ b/ext/posix/config.m4 @@ -17,6 +17,7 @@ if test "$PHP_POSIX" = "yes"; then eaccess getgrgid_r getgroups + getlogin getpgid getrlimit getsid diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 512776d3ced20..ff878b3acfc1b 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -45,6 +45,14 @@ # include #endif +#if (defined(__sun) && !defined(_LP64)) || defined(_AIX) +#define POSIX_PID_MIN LONG_MIN +#define POSIX_PID_MAX LONG_MAX +#else +#define POSIX_PID_MIN INT_MIN +#define POSIX_PID_MAX INT_MAX +#endif + #include "posix_arginfo.h" ZEND_DECLARE_MODULE_GLOBALS(posix) @@ -118,6 +126,12 @@ ZEND_GET_MODULE(posix) } \ RETURN_TRUE; +#define PHP_POSIX_CHECK_PID(pid, arg, lower, upper) \ + if (pid < lower || pid > upper) { \ + zend_argument_value_error(arg, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, lower, upper); \ + RETURN_THROWS(); \ + } + /* {{{ Send a signal to a process (POSIX.1, 3.3.2) */ PHP_FUNCTION(posix_kill) @@ -129,6 +143,8 @@ PHP_FUNCTION(posix_kill) Z_PARAM_LONG(sig) ZEND_PARSE_PARAMETERS_END(); + PHP_POSIX_CHECK_PID(pid, 1, POSIX_PID_MIN, POSIX_PID_MAX) + if (kill(pid, sig) < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; @@ -291,6 +307,9 @@ PHP_FUNCTION(posix_setpgid) Z_PARAM_LONG(pgid) ZEND_PARSE_PARAMETERS_END(); + PHP_POSIX_CHECK_PID(pid, 1, 0, POSIX_PID_MAX) + PHP_POSIX_CHECK_PID(pgid, 2, 0, POSIX_PID_MAX) + if (setpgid(pid, pgid) < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; @@ -329,6 +348,8 @@ PHP_FUNCTION(posix_getsid) Z_PARAM_LONG(val) ZEND_PARSE_PARAMETERS_END(); + PHP_POSIX_CHECK_PID(val, 1, 0, POSIX_PID_MAX) + if ((val = getsid(val)) < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; @@ -1183,6 +1204,21 @@ PHP_FUNCTION(posix_setrlimit) Z_PARAM_LONG(max) ZEND_PARSE_PARAMETERS_END(); + if (cur < -1) { + zend_argument_value_error(2, "must be greater or equal to -1"); + RETURN_THROWS(); + } + + if (max < -1) { + zend_argument_value_error(3, "must be greater or equal to -1"); + RETURN_THROWS(); + } + + if (max > -1 && cur > max) { + zend_argument_value_error(2, "must be lower or equal to " ZEND_LONG_FMT, max); + RETURN_THROWS(); + } + rl.rlim_cur = cur; rl.rlim_max = max; diff --git a/ext/posix/tests/posix_getsid_error.phpt b/ext/posix/tests/posix_getsid_error.phpt index c62eca58a8400..68f1685549979 100644 --- a/ext/posix/tests/posix_getsid_error.phpt +++ b/ext/posix/tests/posix_getsid_error.phpt @@ -9,7 +9,11 @@ PHP Testfest Berlin 2009-05-10 posix --FILE-- getMessage(), PHP_EOL; +} ?> ---EXPECT-- -bool(false) +--EXPECTF-- +posix_getsid(): Argument #1 ($process_id) must be between 0 and %d diff --git a/ext/posix/tests/posix_kill_pidoverflow.phpt b/ext/posix/tests/posix_kill_pidoverflow.phpt new file mode 100644 index 0000000000000..0e8b8c7b7df12 --- /dev/null +++ b/ext/posix/tests/posix_kill_pidoverflow.phpt @@ -0,0 +1,25 @@ +--TEST-- +posix_kill() with large pid +--EXTENSIONS-- +posix +pcntl +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +try { + posix_kill(PHP_INT_MIN, SIGTERM); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +?> +--EXPECTF-- +posix_kill(): Argument #1 ($process_id) must be between %i and %d +posix_kill(): Argument #1 ($process_id) must be between %i and %d diff --git a/ext/posix/tests/posix_setpgid_error.phpt b/ext/posix/tests/posix_setpgid_error.phpt new file mode 100644 index 0000000000000..0d00dd87c60f6 --- /dev/null +++ b/ext/posix/tests/posix_setpgid_error.phpt @@ -0,0 +1,34 @@ +--TEST-- +posix_setpgid() with wrong pid values +--EXTENSIONS-- +posix +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} +try { + posix_setpgid(-2, 1); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + posix_setpgid(1, PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + posix_setpgid(1, -2); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +?> +--EXPECTF-- +posix_setpgid(): Argument #1 ($process_id) must be between 0 and %d +posix_setpgid(): Argument #1 ($process_id) must be between 0 and %d +posix_setpgid(): Argument #2 ($process_group_id) must be between 0 and %d +posix_setpgid(): Argument #2 ($process_group_id) must be between 0 and %d diff --git a/ext/posix/tests/posix_setrlimit.phpt b/ext/posix/tests/posix_setrlimit.phpt index cc8fadafc047e..51638793f9d44 100644 --- a/ext/posix/tests/posix_setrlimit.phpt +++ b/ext/posix/tests/posix_setrlimit.phpt @@ -12,9 +12,25 @@ if (str_contains(PHP_OS, 'FreeBSD')) die('skip different behavior on FreeBSD'); getMessage(), PHP_EOL; +} +try { + posix_setrlimit(POSIX_RLIMIT_NOFILE, -2, -1); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +try { + posix_setrlimit(POSIX_RLIMIT_NOFILE, -1, -2); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} ?> --EXPECT-- bool(true) -bool(false) +posix_setrlimit(): Argument #2 ($soft_limit) must be lower or equal to 128 +posix_setrlimit(): Argument #2 ($soft_limit) must be greater or equal to -1 +posix_setrlimit(): Argument #3 ($hard_limit) must be greater or equal to -1 diff --git a/ext/random/php_random.h b/ext/random/php_random.h index bc55a3defcc7c..9db8c8ba19052 100644 --- a/ext/random/php_random.h +++ b/ext/random/php_random.h @@ -151,7 +151,7 @@ static inline php_random_randomizer *php_random_randomizer_from_obj(zend_object PHPAPI void *php_random_status_alloc(const php_random_algo *algo, const bool persistent); PHPAPI void *php_random_status_copy(const php_random_algo *algo, void *old_status, void *new_status); PHPAPI void php_random_status_free(void *status, const bool persistent); -PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, zend_object_handlers *handlers, const php_random_algo *algo); +PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, const php_random_algo *algo); PHPAPI void php_random_engine_common_free_object(zend_object *object); PHPAPI zend_object *php_random_engine_common_clone_object(zend_object *object); PHPAPI uint32_t php_random_range32(php_random_algo_with_state engine, uint32_t umax); diff --git a/ext/random/random.c b/ext/random/random.c index 46a6c4fd44f2c..f9feaadcbb15f 100644 --- a/ext/random/random.c +++ b/ext/random/random.c @@ -197,22 +197,22 @@ PHPAPI uint64_t php_random_range64(php_random_algo_with_state engine, uint64_t u static zend_object *php_random_engine_mt19937_new(zend_class_entry *ce) { - return &php_random_engine_common_init(ce, &random_engine_mt19937_object_handlers, &php_random_algo_mt19937)->std; + return &php_random_engine_common_init(ce, &php_random_algo_mt19937)->std; } static zend_object *php_random_engine_pcgoneseq128xslrr64_new(zend_class_entry *ce) { - return &php_random_engine_common_init(ce, &random_engine_pcgoneseq128xslrr64_object_handlers, &php_random_algo_pcgoneseq128xslrr64)->std; + return &php_random_engine_common_init(ce, &php_random_algo_pcgoneseq128xslrr64)->std; } static zend_object *php_random_engine_xoshiro256starstar_new(zend_class_entry *ce) { - return &php_random_engine_common_init(ce, &random_engine_xoshiro256starstar_object_handlers, &php_random_algo_xoshiro256starstar)->std; + return &php_random_engine_common_init(ce, &php_random_algo_xoshiro256starstar)->std; } static zend_object *php_random_engine_secure_new(zend_class_entry *ce) { - return &php_random_engine_common_init(ce, &random_engine_secure_object_handlers, &php_random_algo_secure)->std; + return &php_random_engine_common_init(ce, &php_random_algo_secure)->std; } static zend_object *php_random_randomizer_new(zend_class_entry *ce) @@ -250,7 +250,7 @@ PHPAPI void php_random_status_free(void *status, const bool persistent) pefree(status, persistent); } -PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, zend_object_handlers *handlers, const php_random_algo *algo) +PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, const php_random_algo *algo) { php_random_engine *engine = zend_object_alloc(sizeof(php_random_engine), ce); @@ -261,7 +261,6 @@ PHPAPI php_random_engine *php_random_engine_common_init(zend_class_entry *ce, ze .algo = algo, .state = php_random_status_alloc(algo, false) }; - engine->std.handlers = handlers; return engine; } @@ -746,6 +745,7 @@ PHP_MINIT_FUNCTION(random) /* Random\Engine\Mt19937 */ random_ce_Random_Engine_Mt19937 = register_class_Random_Engine_Mt19937(random_ce_Random_Engine); random_ce_Random_Engine_Mt19937->create_object = php_random_engine_mt19937_new; + random_ce_Random_Engine_Mt19937->default_object_handlers = &random_engine_mt19937_object_handlers; memcpy(&random_engine_mt19937_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); random_engine_mt19937_object_handlers.offset = XtOffsetOf(php_random_engine, std); random_engine_mt19937_object_handlers.free_obj = php_random_engine_common_free_object; @@ -754,6 +754,7 @@ PHP_MINIT_FUNCTION(random) /* Random\Engine\PcgOnseq128XslRr64 */ random_ce_Random_Engine_PcgOneseq128XslRr64 = register_class_Random_Engine_PcgOneseq128XslRr64(random_ce_Random_Engine); random_ce_Random_Engine_PcgOneseq128XslRr64->create_object = php_random_engine_pcgoneseq128xslrr64_new; + random_ce_Random_Engine_PcgOneseq128XslRr64->default_object_handlers = &random_engine_pcgoneseq128xslrr64_object_handlers; memcpy(&random_engine_pcgoneseq128xslrr64_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); random_engine_pcgoneseq128xslrr64_object_handlers.offset = XtOffsetOf(php_random_engine, std); random_engine_pcgoneseq128xslrr64_object_handlers.free_obj = php_random_engine_common_free_object; @@ -762,6 +763,7 @@ PHP_MINIT_FUNCTION(random) /* Random\Engine\Xoshiro256StarStar */ random_ce_Random_Engine_Xoshiro256StarStar = register_class_Random_Engine_Xoshiro256StarStar(random_ce_Random_Engine); random_ce_Random_Engine_Xoshiro256StarStar->create_object = php_random_engine_xoshiro256starstar_new; + random_ce_Random_Engine_Xoshiro256StarStar->default_object_handlers = &random_engine_xoshiro256starstar_object_handlers; memcpy(&random_engine_xoshiro256starstar_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); random_engine_xoshiro256starstar_object_handlers.offset = XtOffsetOf(php_random_engine, std); random_engine_xoshiro256starstar_object_handlers.free_obj = php_random_engine_common_free_object; @@ -770,6 +772,7 @@ PHP_MINIT_FUNCTION(random) /* Random\Engine\Secure */ random_ce_Random_Engine_Secure = register_class_Random_Engine_Secure(random_ce_Random_CryptoSafeEngine); random_ce_Random_Engine_Secure->create_object = php_random_engine_secure_new; + random_ce_Random_Engine_Secure->default_object_handlers = &random_engine_secure_object_handlers; memcpy(&random_engine_secure_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); random_engine_secure_object_handlers.offset = XtOffsetOf(php_random_engine, std); random_engine_secure_object_handlers.free_obj = php_random_engine_common_free_object; diff --git a/ext/random/random.stub.php b/ext/random/random.stub.php index b59221bf9180f..2854bdd2c2548 100644 --- a/ext/random/random.stub.php +++ b/ext/random/random.stub.php @@ -10,9 +10,9 @@ const MT_RAND_MT19937 = UNKNOWN; /** * @var int - * @deprecated * @cvalue MT_RAND_PHP */ + #[\Deprecated(since: '8.3', message: 'as it uses a biased non-standard variant of Mt19937')] const MT_RAND_PHP = UNKNOWN; #[\Deprecated(since: '8.4', message: "use \\Random\\Randomizer::getFloat() instead")] diff --git a/ext/random/random_arginfo.h b/ext/random/random_arginfo.h index c1cfb8eb34132..ec22af1bd2b11 100644 --- a/ext/random/random_arginfo.h +++ b/ext/random/random_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 8b30f08404f2912d40f4cb61b76ec283af19b79c */ + * Stub hash: 416be19494555016195600e488d79f0dd35f2620 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_lcg_value, 0, 0, IS_DOUBLE, 0) ZEND_END_ARG_INFO() @@ -226,20 +226,22 @@ static const zend_function_entry class_Random_Randomizer_methods[] = { static void register_random_symbols(int module_number) { REGISTER_LONG_CONSTANT("MT_RAND_MT19937", MT_RAND_MT19937, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MT_RAND_PHP", MT_RAND_PHP, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_MT_RAND_PHP = REGISTER_LONG_CONSTANT("MT_RAND_PHP", MT_RAND_PHP, CONST_PERSISTENT | CONST_DEPRECATED); zend_attribute *attribute_Deprecated_func_lcg_value_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "lcg_value", sizeof("lcg_value") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_lcg_value_0_arg0; - zend_string *attribute_Deprecated_func_lcg_value_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_lcg_value_0_arg0, attribute_Deprecated_func_lcg_value_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_lcg_value_0->args[0].value, &attribute_Deprecated_func_lcg_value_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_lcg_value_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_lcg_value_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_lcg_value_0_arg1; zend_string *attribute_Deprecated_func_lcg_value_0_arg1_str = zend_string_init("use \\Random\\Randomizer::getFloat() instead", strlen("use \\Random\\Randomizer::getFloat() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_lcg_value_0_arg1, attribute_Deprecated_func_lcg_value_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_lcg_value_0->args[1].value, &attribute_Deprecated_func_lcg_value_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_lcg_value_0->args[1].value, attribute_Deprecated_func_lcg_value_0_arg1_str); attribute_Deprecated_func_lcg_value_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_MT_RAND_PHP_0 = zend_add_global_constant_attribute(const_MT_RAND_PHP, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_MT_RAND_PHP_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); + attribute_Deprecated_const_MT_RAND_PHP_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_MT_RAND_PHP_0_arg1_str = zend_string_init("as it uses a biased non-standard variant of Mt19937", strlen("as it uses a biased non-standard variant of Mt19937"), 1); + ZVAL_STR(&attribute_Deprecated_const_MT_RAND_PHP_0->args[1].value, attribute_Deprecated_const_MT_RAND_PHP_0_arg1_str); + attribute_Deprecated_const_MT_RAND_PHP_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_Random_Engine_Mt19937(zend_class_entry *class_entry_Random_Engine) diff --git a/ext/random/randomizer.c b/ext/random/randomizer.c index 4f63388e8f56a..fc3c93fc2b053 100644 --- a/ext/random/randomizer.c +++ b/ext/random/randomizer.c @@ -43,16 +43,9 @@ static inline void randomizer_common_init(php_random_randomizer *randomizer, zen .state = state, }; - zend_string *mname; - zend_function *generate_method; - - mname = ZSTR_INIT_LITERAL("generate", 0); - generate_method = zend_hash_find_ptr(&engine_object->ce->function_table, mname); - zend_string_release(mname); - /* Create compatible state */ state->object = engine_object; - state->generate_method = generate_method; + state->generate_method = zend_hash_str_find_ptr(&engine_object->ce->function_table, "generate", strlen("generate")); /* Mark self-allocated for memory management */ randomizer->is_userland_algo = true; @@ -196,7 +189,7 @@ PHP_METHOD(Random_Randomizer, getFloat) RETVAL_DOUBLE(php_random_gammasection_open_open(randomizer->engine, min, max)); if (UNEXPECTED(isnan(Z_DVAL_P(return_value)))) { - zend_value_error("The given interval is empty, there are no floats between argument #1 ($min) and argument #2 ($max)."); + zend_value_error("The given interval is empty, there are no floats between argument #1 ($min) and argument #2 ($max)"); RETURN_THROWS(); } diff --git a/ext/random/tests/01_functions/array_rand_mt_rand_php.phpt b/ext/random/tests/01_functions/array_rand_mt_rand_php.phpt index 703460a890f05..ee3e155484dde 100644 --- a/ext/random/tests/01_functions/array_rand_mt_rand_php.phpt +++ b/ext/random/tests/01_functions/array_rand_mt_rand_php.phpt @@ -24,7 +24,7 @@ var_dump( ); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d string(11) "found key 0" diff --git a/ext/random/tests/01_functions/bug75514.phpt b/ext/random/tests/01_functions/bug75514.phpt index 583ac9a209ef3..8f90064966988 100644 --- a/ext/random/tests/01_functions/bug75514.phpt +++ b/ext/random/tests/01_functions/bug75514.phpt @@ -6,7 +6,7 @@ mt_srand(0, MT_RAND_PHP); var_dump(mt_rand(0,999999999), mt_rand(0,999)); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d int(448865905) diff --git a/ext/random/tests/01_functions/mt_rand_value.phpt b/ext/random/tests/01_functions/mt_rand_value.phpt index ede620648e16b..bf5fdfc2a4e88 100644 --- a/ext/random/tests/01_functions/mt_rand_value.phpt +++ b/ext/random/tests/01_functions/mt_rand_value.phpt @@ -38,7 +38,7 @@ echo $x.PHP_EOL; ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d 1614640687 diff --git a/ext/random/tests/03_randomizer/compatibility_mt_rand.phpt b/ext/random/tests/03_randomizer/compatibility_mt_rand.phpt index 4abb1276f3665..50aa7b3efb0d8 100644 --- a/ext/random/tests/03_randomizer/compatibility_mt_rand.phpt +++ b/ext/random/tests/03_randomizer/compatibility_mt_rand.phpt @@ -46,11 +46,11 @@ die('success'); --EXPECTF-- MT_RAND_PHP -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d MT_RAND_MT19937 diff --git a/ext/random/tests/03_randomizer/gh_19765_unserialize.phpt b/ext/random/tests/03_randomizer/gh_19765_unserialize.phpt new file mode 100644 index 0000000000000..24abfca293fc5 --- /dev/null +++ b/ext/random/tests/03_randomizer/gh_19765_unserialize.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-19765: object_properties_load() bypasses readonly property checks +--FILE-- +__unserialize([['engine' => new PcgOneseq128XslRr64()]]); +} catch (Exception $error) { + echo $error->getMessage() . "\n"; +} +var_dump($r->engine::class); + +?> +--EXPECT-- +Invalid serialization data for Random\Randomizer object +string(21) "Random\Engine\Mt19937" diff --git a/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt b/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt index fe1acb2f74be4..edadb7380bd1f 100644 --- a/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt +++ b/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt @@ -1,5 +1,5 @@ --TEST-- -Fix GH-9186 @strict-properties can be bypassed using unserialization +GH-9186: @strict-properties can be bypassed using unserialization --FILE-- --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/getBytesFromString.phpt b/ext/random/tests/03_randomizer/methods/getBytesFromString.phpt index 06d24cc82bd23..8189d061d9701 100644 --- a/ext/random/tests/03_randomizer/methods/getBytesFromString.phpt +++ b/ext/random/tests/03_randomizer/methods/getBytesFromString.phpt @@ -43,7 +43,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/getFloat.phpt b/ext/random/tests/03_randomizer/methods/getFloat.phpt index 8655777f89c3a..c07fedcc210e4 100644 --- a/ext/random/tests/03_randomizer/methods/getFloat.phpt +++ b/ext/random/tests/03_randomizer/methods/getFloat.phpt @@ -42,7 +42,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/getFloat_error.phpt b/ext/random/tests/03_randomizer/methods/getFloat_error.phpt index 286435e1752fb..42e933cbefb29 100644 --- a/ext/random/tests/03_randomizer/methods/getFloat_error.phpt +++ b/ext/random/tests/03_randomizer/methods/getFloat_error.phpt @@ -127,4 +127,4 @@ Random\Randomizer::getFloat(): Argument #2 ($max) must be finite Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) Random\Randomizer::getFloat(): Argument #2 ($max) must be greater than argument #1 ($min) -The given interval is empty, there are no floats between argument #1 ($min) and argument #2 ($max). +The given interval is empty, there are no floats between argument #1 ($min) and argument #2 ($max) diff --git a/ext/random/tests/03_randomizer/methods/getInt.phpt b/ext/random/tests/03_randomizer/methods/getInt.phpt index ba936dcf3bf0f..5f1656c615a7f 100644 --- a/ext/random/tests/03_randomizer/methods/getInt.phpt +++ b/ext/random/tests/03_randomizer/methods/getInt.phpt @@ -46,7 +46,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/nextFloat.phpt b/ext/random/tests/03_randomizer/methods/nextFloat.phpt index b515242137506..62243faf434a7 100644 --- a/ext/random/tests/03_randomizer/methods/nextFloat.phpt +++ b/ext/random/tests/03_randomizer/methods/nextFloat.phpt @@ -41,7 +41,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/nextInt.phpt b/ext/random/tests/03_randomizer/methods/nextInt.phpt index 008e5acb259e8..6739ae9f1cf55 100644 --- a/ext/random/tests/03_randomizer/methods/nextInt.phpt +++ b/ext/random/tests/03_randomizer/methods/nextInt.phpt @@ -41,7 +41,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/pickArrayKeys.phpt b/ext/random/tests/03_randomizer/methods/pickArrayKeys.phpt index d5b159f2af136..8c799909c8749 100644 --- a/ext/random/tests/03_randomizer/methods/pickArrayKeys.phpt +++ b/ext/random/tests/03_randomizer/methods/pickArrayKeys.phpt @@ -76,7 +76,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/shuffleArray.phpt b/ext/random/tests/03_randomizer/methods/shuffleArray.phpt index af4ce88b3821d..302e683edbf20 100644 --- a/ext/random/tests/03_randomizer/methods/shuffleArray.phpt +++ b/ext/random/tests/03_randomizer/methods/shuffleArray.phpt @@ -45,7 +45,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/methods/shuffleBytes.phpt b/ext/random/tests/03_randomizer/methods/shuffleBytes.phpt index 404b670e2863a..cacf3688bb310 100644 --- a/ext/random/tests/03_randomizer/methods/shuffleBytes.phpt +++ b/ext/random/tests/03_randomizer/methods/shuffleBytes.phpt @@ -52,7 +52,7 @@ die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/random/tests/03_randomizer/serialize.phpt b/ext/random/tests/03_randomizer/serialize.phpt index 1f56228d33220..4ac8bfe6e682a 100644 --- a/ext/random/tests/03_randomizer/serialize.phpt +++ b/ext/random/tests/03_randomizer/serialize.phpt @@ -43,7 +43,7 @@ foreach ($engines as $engine) { die('success'); ?> --EXPECTF-- -Deprecated: Constant MT_RAND_PHP is deprecated in %s on line %d +Deprecated: Constant MT_RAND_PHP is deprecated since 8.3, as it uses a biased non-standard variant of Mt19937 in %s on line %d Deprecated: The MT_RAND_PHP variant of Mt19937 is deprecated in %s on line %d Random\Engine\Mt19937 diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 8ef0269481cf7..3d025c7eefd7c 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -716,7 +716,7 @@ static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) { return RT_CONSTANT(recv, recv->op2); } -static int format_default_value(smart_str *str, zval *value) { +static void format_default_value(smart_str *str, zval *value) { if (smart_str_append_zval(str, value, SIZE_MAX) == SUCCESS) { /* Nothing to do. */ } else if (Z_TYPE_P(value) == IS_ARRAY) { @@ -761,7 +761,6 @@ static int format_default_value(smart_str *str, zval *value) { smart_str_append(str, ast_str); zend_string_release(ast_str); } - return SUCCESS; } static inline bool has_internal_arg_info(const zend_function *fptr) { @@ -808,9 +807,7 @@ static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_ zval *default_value = get_default_from_recv((zend_op_array*)fptr, offset); if (default_value) { smart_str_appends(str, " = "); - if (format_default_value(str, default_value) == FAILURE) { - return; - } + format_default_value(str, default_value); } } } @@ -1040,6 +1037,9 @@ static void _property_string(smart_str *str, zend_property_info *prop, const cha if (prop->flags & ZEND_ACC_READONLY) { smart_str_appends(str, "readonly "); } + if (prop->flags & ZEND_ACC_VIRTUAL) { + smart_str_appends(str, "virtual "); + } if (ZEND_TYPE_IS_SET(prop->type)) { zend_string *type_str = zend_type_to_string(prop->type); smart_str_append(str, type_str); @@ -1055,9 +1055,27 @@ static void _property_string(smart_str *str, zend_property_info *prop, const cha zval *default_value = property_get_default(prop); if (default_value && !Z_ISUNDEF_P(default_value)) { smart_str_appends(str, " = "); - if (format_default_value(str, default_value) == FAILURE) { - return; + format_default_value(str, default_value); + } + if (prop->hooks != NULL) { + smart_str_appends(str, " {"); + const zend_function *get_hooked = prop->hooks[ZEND_PROPERTY_HOOK_GET]; + if (get_hooked != NULL) { + if (get_hooked->common.fn_flags & ZEND_ACC_FINAL) { + smart_str_appends(str, " final get;"); + } else { + smart_str_appends(str, " get;"); + } } + const zend_function *set_hooked = prop->hooks[ZEND_PROPERTY_HOOK_SET]; + if (set_hooked != NULL) { + if (set_hooked->common.fn_flags & ZEND_ACC_FINAL) { + smart_str_appends(str, " final set;"); + } else { + smart_str_appends(str, " set;"); + } + } + smart_str_appends(str, " }"); } } @@ -1255,7 +1273,7 @@ static void reflection_attribute_factory(zval *object, HashTable *attributes, ze } /* }}} */ -static int read_attributes(zval *ret, HashTable *attributes, zend_class_entry *scope, +static zend_result read_attributes(zval *ret, HashTable *attributes, zend_class_entry *scope, uint32_t offset, uint32_t target, zend_string *name, zend_class_entry *base, zend_string *filename) /* {{{ */ { ZEND_ASSERT(attributes != NULL); @@ -1635,7 +1653,7 @@ static void reflection_enum_case_factory(zend_class_entry *ce, zend_string *name ZVAL_STR_COPY(reflection_prop_class(object), constant->ce->name); } -static int get_parameter_default(zval *result, parameter_reference *param) { +static zend_result get_parameter_default(zval *result, parameter_reference *param) { if (param->fptr->type == ZEND_INTERNAL_FUNCTION) { if (param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO) { /* We don't have a way to determine the default value for this case right now. */ @@ -1695,6 +1713,15 @@ ZEND_METHOD(Reflection, getModifierNames) add_next_index_stringl(return_value, "protected", sizeof("protected")-1); break; } + /* These are also mutually exclusive */ + switch (modifiers & ZEND_ACC_PPP_SET_MASK) { + case ZEND_ACC_PROTECTED_SET: + add_next_index_stringl(return_value, "protected(set)", sizeof("protected(set)")-1); + break; + case ZEND_ACC_PRIVATE_SET: + add_next_index_stringl(return_value, "private(set)", sizeof("private(set)")-1); + break; + } if (modifiers & ZEND_ACC_STATIC) { add_next_index_str(return_value, ZSTR_KNOWN(ZEND_STR_STATIC)); @@ -2844,7 +2871,7 @@ ZEND_METHOD(ReflectionParameter, isCallable) } /* }}} */ -/* {{{ Returns whether NULL is allowed as this parameters's value */ +/* {{{ Returns whether NULL is allowed as this parameter's value */ ZEND_METHOD(ReflectionParameter, allowsNull) { reflection_object *intern; @@ -4190,7 +4217,7 @@ ZEND_METHOD(ReflectionClass, getStaticProperties) ZEND_METHOD(ReflectionClass, getStaticPropertyValue) { reflection_object *intern; - zend_class_entry *ce, *old_scope; + zend_class_entry *ce; zend_string *name; zval *prop, *def_value = NULL; @@ -4204,7 +4231,7 @@ ZEND_METHOD(ReflectionClass, getStaticPropertyValue) RETURN_THROWS(); } - old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = ce; prop = zend_std_get_static_property(ce, name, BP_VAR_IS); EG(fake_scope) = old_scope; @@ -4231,7 +4258,7 @@ ZEND_METHOD(ReflectionClass, getStaticPropertyValue) ZEND_METHOD(ReflectionClass, setStaticPropertyValue) { reflection_object *intern; - zend_class_entry *ce, *old_scope; + zend_class_entry *ce; zend_property_info *prop_info; zend_string *name; zval *variable_ptr, *value; @@ -4245,7 +4272,7 @@ ZEND_METHOD(ReflectionClass, setStaticPropertyValue) if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { RETURN_THROWS(); } - old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = ce; variable_ptr = zend_std_get_static_property_with_info(ce, name, BP_VAR_W, &prop_info); EG(fake_scope) = old_scope; @@ -4505,16 +4532,16 @@ ZEND_METHOD(ReflectionClass, getMethod) static bool _addmethod(zend_function *mptr, zend_class_entry *ce, HashTable *ht, zend_long filter) { if ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && mptr->common.scope != ce) { - return 0; + return false; } if (mptr->common.fn_flags & filter) { zval method; reflection_method_factory(ce, mptr, NULL, &method); zend_hash_next_index_insert_new(ht, &method); - return 1; + return true; } - return 0; + return false; } /* }}} */ @@ -4837,6 +4864,11 @@ ZEND_METHOD(ReflectionClass, getConstant) } } ZEND_HASH_FOREACH_END(); if ((c = zend_hash_find_ptr(constants_table, name)) == NULL) { + zend_error( + E_DEPRECATED, + "ReflectionClass::getConstant() for a non-existent constant is deprecated, " + "use ReflectionClass::hasConstant() to check if the constant exists" + ); RETURN_FALSE; } ZVAL_COPY_OR_DUP(return_value, &c->value); @@ -4998,7 +5030,7 @@ ZEND_METHOD(ReflectionClass, isInstance) ZEND_METHOD(ReflectionClass, newInstance) { reflection_object *intern; - zend_class_entry *ce, *old_scope; + zend_class_entry *ce; zend_function *constructor; GET_REFLECTION_OBJECT_PTR(ce); @@ -5007,7 +5039,7 @@ ZEND_METHOD(ReflectionClass, newInstance) return; } - old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = ce; constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value)); EG(fake_scope) = old_scope; @@ -5065,7 +5097,7 @@ ZEND_METHOD(ReflectionClass, newInstanceWithoutConstructor) ZEND_METHOD(ReflectionClass, newInstanceArgs) { reflection_object *intern; - zend_class_entry *ce, *old_scope; + zend_class_entry *ce; int argc = 0; HashTable *args = NULL; zend_function *constructor; @@ -5084,7 +5116,7 @@ ZEND_METHOD(ReflectionClass, newInstanceArgs) return; } - old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = ce; constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value)); EG(fake_scope) = old_scope; @@ -5753,6 +5785,21 @@ ZEND_METHOD(ReflectionProperty, getName) } /* }}} */ +ZEND_METHOD(ReflectionProperty, getMangledName) +{ + reflection_object *intern; + property_reference *ref; + + ZEND_PARSE_PARAMETERS_NONE(); + + GET_REFLECTION_OBJECT_PTR(ref); + if (ref->prop == NULL) { + RETURN_STR_COPY(ref->unmangled_name); + } + + RETURN_STR_COPY(ref->prop->name); +} + static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */ { reflection_object *intern; @@ -5908,7 +5955,7 @@ ZEND_METHOD(ReflectionProperty, getValue) } } - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = intern->ce; member_p = Z_OBJ_P(object)->handlers->read_property(Z_OBJ_P(object), ref->unmangled_name, BP_VAR_R, ref->cache_slot, &rv); @@ -5967,7 +6014,7 @@ ZEND_METHOD(ReflectionProperty, setValue) Z_PARAM_ZVAL(value) ZEND_PARSE_PARAMETERS_END(); - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = intern->ce; object->handlers->write_property(object, ref->unmangled_name, value, ref->cache_slot); EG(fake_scope) = old_scope; @@ -6026,7 +6073,7 @@ ZEND_METHOD(ReflectionProperty, getRawValue) if (!prop || !prop->hooks || !prop->hooks[ZEND_PROPERTY_HOOK_GET]) { zval rv; - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = intern->ce; zval *member_p = Z_OBJ_P(object)->handlers->read_property( Z_OBJ_P(object), ref->unmangled_name, BP_VAR_R, @@ -6052,7 +6099,7 @@ static void reflection_property_set_raw_value(zend_property_info *prop, zend_object *object, zval *value) { if (!prop || !prop->hooks || !prop->hooks[ZEND_PROPERTY_HOOK_SET]) { - zend_class_entry *old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = intern->ce; object->handlers->write_property(object, unmangled_name, value, cache_slot); EG(fake_scope) = old_scope; @@ -6275,7 +6322,6 @@ ZEND_METHOD(ReflectionProperty, isInitialized) } RETURN_FALSE; } else { - zend_class_entry *old_scope; int retval; if (!object) { @@ -6298,7 +6344,7 @@ ZEND_METHOD(ReflectionProperty, isInitialized) } } - old_scope = EG(fake_scope); + const zend_class_entry *old_scope = EG(fake_scope); EG(fake_scope) = intern->ce; retval = Z_OBJ_HT_P(object)->has_property(Z_OBJ_P(object), ref->unmangled_name, ZEND_PROPERTY_EXISTS, ref->cache_slot); @@ -6404,7 +6450,7 @@ ZEND_METHOD(ReflectionProperty, getSettableType) /* Get-only virtual property can never be written to. */ if (prop->hooks && (prop->flags & ZEND_ACC_VIRTUAL) && !prop->hooks[ZEND_PROPERTY_HOOK_SET]) { zend_type never_type = ZEND_TYPE_INIT_CODE(IS_NEVER, 0, 0); - reflection_type_factory(never_type, return_value, 0); + reflection_type_factory(never_type, return_value, 1); return; } @@ -6414,7 +6460,7 @@ ZEND_METHOD(ReflectionProperty, getSettableType) if (!ZEND_TYPE_IS_SET(arg_info->type)) { RETURN_NULL(); } - reflection_type_factory(arg_info->type, return_value, 0); + reflection_type_factory(arg_info->type, return_value, 1); return; } @@ -6422,7 +6468,7 @@ ZEND_METHOD(ReflectionProperty, getSettableType) if (!ZEND_TYPE_IS_SET(ref->prop->type)) { RETURN_NULL(); } - reflection_type_factory(ref->prop->type, return_value, 0); + reflection_type_factory(ref->prop->type, return_value, 1); } /* {{{ Returns whether property has a type */ @@ -6477,11 +6523,22 @@ ZEND_METHOD(ReflectionProperty, getDefaultValue) prop_info = ref->prop; if (prop_info == NULL) { - return; // throw exception? + // Dynamic property + zend_error( + E_DEPRECATED, + "ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, " + "use ReflectionProperty::hasDefaultValue() to check if the default value exists" + ); + return; } prop = property_get_default(prop_info); if (!prop || Z_ISUNDEF_P(prop)) { + zend_error( + E_DEPRECATED, + "ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, " + "use ReflectionProperty::hasDefaultValue() to check if the default value exists" + ); return; } @@ -7052,7 +7109,7 @@ ZEND_METHOD(ReflectionReference, __construct) static bool is_ignorable_reference(HashTable *ht, zval *ref) { if (Z_REFCOUNT_P(ref) != 1) { - return 0; + return false; } /* Directly self-referential arrays are treated as proper references @@ -7167,10 +7224,7 @@ ZEND_METHOD(ReflectionAttribute, __toString) smart_str_appends(&str, " = "); } - if (format_default_value(&str, &attr->data->args[i].value) == FAILURE) { - smart_str_free(&str); - RETURN_THROWS(); - } + format_default_value(&str, &attr->data->args[i].value); smart_str_appends(&str, " ]\n"); } @@ -7276,26 +7330,61 @@ ZEND_METHOD(ReflectionAttribute, newInstance) RETURN_THROWS(); } - if (ce->type == ZEND_USER_CLASS) { - uint32_t flags = zend_attribute_attribute_get_flags(marker, ce); - if (EG(exception)) { - RETURN_THROWS(); - } + /* This code can be reached under one of three possible conditions: + * - the attribute is an internal attribute, and it had the target and + * and repetition validated already + * - the attribute is an internal attribute and repetition was validated + * already, the internal validator might have been run if the target was + * correct, but any error would have been stored in + * `zend_attribute.validation_error` instead of being thrown due to the + * presence of #[DelayedTargetValidation] + * - the attribute is a user attribute, and neither target nor repetition + * have been validated. + */ + uint32_t flags = zend_attribute_attribute_get_flags(marker, ce); + if (EG(exception)) { + RETURN_THROWS(); + } - if (!(attr->target & flags)) { - zend_string *location = zend_get_attribute_target_names(attr->target); - zend_string *allowed = zend_get_attribute_target_names(flags); + /* No harm in always running target validation, for internal attributes + * without #[DelayedTargetValidation] it isn't necessary but will always + * succeed. */ + if (!(attr->target & flags)) { + zend_string *location = zend_get_attribute_target_names(attr->target); + zend_string *allowed = zend_get_attribute_target_names(flags); - zend_throw_error(NULL, "Attribute \"%s\" cannot target %s (allowed targets: %s)", - ZSTR_VAL(attr->data->name), ZSTR_VAL(location), ZSTR_VAL(allowed) - ); + zend_throw_error(NULL, "Attribute \"%s\" cannot target %s (allowed targets: %s)", + ZSTR_VAL(attr->data->name), ZSTR_VAL(location), ZSTR_VAL(allowed) + ); - zend_string_release(location); - zend_string_release(allowed); + zend_string_release(location); + zend_string_release(allowed); - RETURN_THROWS(); - } + RETURN_THROWS(); + } + if (attr->data->validation_error != NULL) { + /* Delayed validation errors should only be set for internal attributes. */ + ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS); + /* Delayed validation errors should only be set when + * #[\DelayedTargetValidation] is used. Searching for the attribute is + * more expensive than just an assertion and so we don't worry about it + * for non-debug builds. See discussion on GH-18817. */ +#if ZEND_DEBUG + zend_attribute *delayed_target_validation = zend_get_attribute_str( + attr->attributes, + "delayedtargetvalidation", + strlen("delayedtargetvalidation") + ); + ZEND_ASSERT(delayed_target_validation != NULL); +#endif + zend_throw_exception(zend_ce_error, ZSTR_VAL(attr->data->validation_error), 0); + RETURN_THROWS(); + } + + /* Repetition validation is done even if #[DelayedTargetValidation] is used + * and so can be skipped for internal attributes. */ + if (ce->type == ZEND_USER_CLASS) { if (!(flags & ZEND_ATTRIBUTE_IS_REPEATABLE)) { if (zend_is_attribute_repeated(attr->attributes, attr->data)) { zend_throw_error(NULL, "Attribute \"%s\" must not be repeated", ZSTR_VAL(attr->data->name)); diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 63518b446ad86..7af884953bef3 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -226,6 +226,7 @@ public function getPrototype(): ReflectionMethod {} public function hasPrototype(): bool {} /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: "as it has no effect")] public function setAccessible(bool $accessible): void {} } @@ -482,6 +483,8 @@ public function __toString(): string {} /** @tentative-return-type */ public function getName(): string {} + public function getMangledName(): string {} + /** @tentative-return-type */ public function getValue(?object $object = null): mixed {} @@ -540,6 +543,7 @@ public function getDeclaringClass(): ReflectionClass {} public function getDocComment(): string|false {} /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: "as it has no effect")] public function setAccessible(bool $accessible): void {} /** @tentative-return-type */ diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index d50dc04ae3d15..907ada13efab1 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7a8d126a96f0115783bd20a9adfc6bdc5ee88fda */ + * Stub hash: 0f6ecac0c6c4fb4af140a1be95f6a50c7532dae9 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -381,6 +381,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionProperty_getName arginfo_class_ReflectionFunctionAbstract_getName +#define arginfo_class_ReflectionProperty_getMangledName arginfo_class_ReflectionFunction___toString + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_getValue, 0, 0, IS_MIXED, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, object, IS_OBJECT, 1, "null") ZEND_END_ARG_INFO() @@ -853,6 +855,7 @@ ZEND_METHOD(ReflectionObject, __construct); ZEND_METHOD(ReflectionProperty, __construct); ZEND_METHOD(ReflectionProperty, __toString); ZEND_METHOD(ReflectionProperty, getName); +ZEND_METHOD(ReflectionProperty, getMangledName); ZEND_METHOD(ReflectionProperty, getValue); ZEND_METHOD(ReflectionProperty, setValue); ZEND_METHOD(ReflectionProperty, getRawValue); @@ -1073,7 +1076,7 @@ static const zend_function_entry class_ReflectionMethod_methods[] = { ZEND_ME(ReflectionMethod, getDeclaringClass, arginfo_class_ReflectionMethod_getDeclaringClass, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionMethod, getPrototype, arginfo_class_ReflectionMethod_getPrototype, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionMethod, hasPrototype, arginfo_class_ReflectionMethod_hasPrototype, ZEND_ACC_PUBLIC) - ZEND_ME(ReflectionMethod, setAccessible, arginfo_class_ReflectionMethod_setAccessible, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionMethod, setAccessible, arginfo_class_ReflectionMethod_setAccessible, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_FE_END }; @@ -1155,6 +1158,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = { ZEND_ME(ReflectionProperty, __construct, arginfo_class_ReflectionProperty___construct, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, __toString, arginfo_class_ReflectionProperty___toString, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getName, arginfo_class_ReflectionProperty_getName, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionProperty, getMangledName, arginfo_class_ReflectionProperty_getMangledName, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getValue, arginfo_class_ReflectionProperty_getValue, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, setValue, arginfo_class_ReflectionProperty_setValue, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getRawValue, arginfo_class_ReflectionProperty_getRawValue, ZEND_ACC_PUBLIC) @@ -1178,7 +1182,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = { ZEND_ME(ReflectionProperty, getModifiers, arginfo_class_ReflectionProperty_getModifiers, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getDeclaringClass, arginfo_class_ReflectionProperty_getDeclaringClass, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getDocComment, arginfo_class_ReflectionProperty_getDocComment, ZEND_ACC_PUBLIC) - ZEND_ME(ReflectionProperty, setAccessible, arginfo_class_ReflectionProperty_setAccessible, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionProperty, setAccessible, arginfo_class_ReflectionProperty_setAccessible, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(ReflectionProperty, getType, arginfo_class_ReflectionProperty_getType, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, getSettableType, arginfo_class_ReflectionProperty_getSettableType, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionProperty, hasType, arginfo_class_ReflectionProperty_hasType, ZEND_ACC_PUBLIC) @@ -1423,15 +1427,10 @@ static zend_class_entry *register_class_ReflectionFunction(zend_class_entry *cla zend_attribute *attribute_Deprecated_func_isdisabled_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "isdisabled", sizeof("isdisabled") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_isdisabled_0_arg0; - zend_string *attribute_Deprecated_func_isdisabled_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_isdisabled_0_arg0, attribute_Deprecated_func_isdisabled_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_isdisabled_0->args[0].value, &attribute_Deprecated_func_isdisabled_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_isdisabled_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_isdisabled_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_isdisabled_0_arg1; zend_string *attribute_Deprecated_func_isdisabled_0_arg1_str = zend_string_init("as ReflectionFunction can no longer be constructed for disabled functions", strlen("as ReflectionFunction can no longer be constructed for disabled functions"), 1); - ZVAL_STR(&attribute_Deprecated_func_isdisabled_0_arg1, attribute_Deprecated_func_isdisabled_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_isdisabled_0->args[1].value, &attribute_Deprecated_func_isdisabled_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_isdisabled_0->args[1].value, attribute_Deprecated_func_isdisabled_0_arg1_str); attribute_Deprecated_func_isdisabled_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); return class_entry; @@ -1494,6 +1493,14 @@ static zend_class_entry *register_class_ReflectionMethod(zend_class_entry *class ZVAL_UNDEF(&property_class_default_value); zend_declare_typed_property(class_entry, ZSTR_KNOWN(ZEND_STR_CLASS), &property_class_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + + zend_attribute *attribute_Deprecated_func_setaccessible_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setaccessible", sizeof("setaccessible") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_setaccessible_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_setaccessible_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_setaccessible_0_arg1_str = zend_string_init("as it has no effect", strlen("as it has no effect"), 1); + ZVAL_STR(&attribute_Deprecated_func_setaccessible_0->args[1].value, attribute_Deprecated_func_setaccessible_0_arg1_str); + attribute_Deprecated_func_setaccessible_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + return class_entry; } @@ -1651,6 +1658,14 @@ static zend_class_entry *register_class_ReflectionProperty(zend_class_entry *cla ZVAL_UNDEF(&property_class_default_value); zend_declare_typed_property(class_entry, ZSTR_KNOWN(ZEND_STR_CLASS), &property_class_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + + zend_attribute *attribute_Deprecated_func_setaccessible_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "setaccessible", sizeof("setaccessible") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_setaccessible_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_setaccessible_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_setaccessible_0_arg1_str = zend_string_init("as it has no effect", strlen("as it has no effect"), 1); + ZVAL_STR(&attribute_Deprecated_func_setaccessible_0->args[1].value, attribute_Deprecated_func_setaccessible_0_arg1_str); + attribute_Deprecated_func_setaccessible_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + return class_entry; } @@ -1711,39 +1726,22 @@ static zend_class_entry *register_class_ReflectionParameter(zend_class_entry *cl zend_attribute *attribute_Deprecated_func_getclass_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "getclass", sizeof("getclass") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_getclass_0_arg0; - zend_string *attribute_Deprecated_func_getclass_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_getclass_0_arg0, attribute_Deprecated_func_getclass_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_getclass_0->args[0].value, &attribute_Deprecated_func_getclass_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_getclass_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_getclass_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_getclass_0_arg1; zend_string *attribute_Deprecated_func_getclass_0_arg1_str = zend_string_init("use ReflectionParameter::getType() instead", strlen("use ReflectionParameter::getType() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_getclass_0_arg1, attribute_Deprecated_func_getclass_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_getclass_0->args[1].value, &attribute_Deprecated_func_getclass_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_getclass_0->args[1].value, attribute_Deprecated_func_getclass_0_arg1_str); attribute_Deprecated_func_getclass_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_isarray_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "isarray", sizeof("isarray") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_isarray_0_arg0; - zend_string *attribute_Deprecated_func_isarray_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_isarray_0_arg0, attribute_Deprecated_func_isarray_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_isarray_0->args[0].value, &attribute_Deprecated_func_isarray_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_isarray_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_isarray_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_isarray_0_arg1; - zend_string *attribute_Deprecated_func_isarray_0_arg1_str = zend_string_init("use ReflectionParameter::getType() instead", strlen("use ReflectionParameter::getType() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_isarray_0_arg1, attribute_Deprecated_func_isarray_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_isarray_0->args[1].value, &attribute_Deprecated_func_isarray_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_isarray_0->args[1].value, attribute_Deprecated_func_getclass_0_arg1_str); attribute_Deprecated_func_isarray_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_iscallable_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "iscallable", sizeof("iscallable") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_iscallable_0_arg0; - zend_string *attribute_Deprecated_func_iscallable_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_iscallable_0_arg0, attribute_Deprecated_func_iscallable_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_iscallable_0->args[0].value, &attribute_Deprecated_func_iscallable_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_iscallable_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_iscallable_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_iscallable_0_arg1; - zend_string *attribute_Deprecated_func_iscallable_0_arg1_str = zend_string_init("use ReflectionParameter::getType() instead", strlen("use ReflectionParameter::getType() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_iscallable_0_arg1, attribute_Deprecated_func_iscallable_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_iscallable_0->args[1].value, &attribute_Deprecated_func_iscallable_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_iscallable_0->args[1].value, attribute_Deprecated_func_getclass_0_arg1_str); attribute_Deprecated_func_iscallable_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); return class_entry; diff --git a/ext/reflection/tests/022.phpt b/ext/reflection/tests/022.phpt index 4a6738f97cd27..7a78397a76f0a 100644 --- a/ext/reflection/tests/022.phpt +++ b/ext/reflection/tests/022.phpt @@ -9,6 +9,8 @@ $class = new ReflectionClass("Foo"); var_dump($class->getConstant("c1")); var_dump($class->getConstant("c2")); ?> ---EXPECT-- +--EXPECTF-- int(1) + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) diff --git a/ext/reflection/tests/ReflectionClass_getConstant_basic.phpt b/ext/reflection/tests/ReflectionClass_getConstant_basic.phpt index 67d1eee7e8374..a8864c5970a9c 100644 --- a/ext/reflection/tests/ReflectionClass_getConstant_basic.phpt +++ b/ext/reflection/tests/ReflectionClass_getConstant_basic.phpt @@ -23,19 +23,31 @@ foreach($classes as $class) { var_dump($rc->getConstant('doesnotexist')); } ?> ---EXPECT-- +--EXPECTF-- Reflecting on class C: string(12) "hello from C" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on class D: string(12) "hello from C" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on class E: string(12) "hello from C" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on class F: string(12) "hello from F" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on class X: + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) diff --git a/ext/reflection/tests/ReflectionClass_getConstant_error.phpt b/ext/reflection/tests/ReflectionClass_getConstant_error.phpt index d143006af9992..caadf2e3713f6 100644 --- a/ext/reflection/tests/ReflectionClass_getConstant_error.phpt +++ b/ext/reflection/tests/ReflectionClass_getConstant_error.phpt @@ -12,8 +12,14 @@ var_dump($rc->getConstant(1)); var_dump($rc->getConstant(1.5)); var_dump($rc->getConstant(true)); ?> ---EXPECT-- +--EXPECTF-- Check invalid params: + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) diff --git a/ext/reflection/tests/ReflectionClass_toString_008.phpt b/ext/reflection/tests/ReflectionClass_toString_008.phpt new file mode 100644 index 0000000000000..15131cfd880a0 --- /dev/null +++ b/ext/reflection/tests/ReflectionClass_toString_008.phpt @@ -0,0 +1,165 @@ +--TEST-- +Using ReflectionClass::__toString() with hooked properties (GH-17927) +--FILE-- + "always this string"; + } + public mixed $setOnly { + set => strtolower($value); + } + public mixed $both { + get => $this->prop3; + set => strtolower($value); + } +} +class WithFinalHooks { + public mixed $getOnly { + final get => "always this string"; + } + public mixed $setOnly { + final set => strtolower($value); + } + public mixed $both { + final get => $this->prop3; + final set => strtolower($value); + } +} +class WithMixedHooks { + public mixed $getIsFinal { + final get => "always this string"; + set => strtolower($value); + } + public mixed $setIsFinal { + get => $this->setIsFinal; + final set => strtolower($value); + } +} +$classes = [ + IHookedDemo::class, + HookedDemo::class, + WithHooks::class, + WithFinalHooks::class, + WithMixedHooks::class, +]; +foreach ( $classes as $clazz ) { + echo new ReflectionClass( $clazz ); +} +?> +--EXPECTF-- +Interface [ interface IHookedDemo ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [3] { + Property [ abstract public virtual mixed $getOnly { get; } ] + Property [ abstract public virtual mixed $setOnly { set; } ] + Property [ abstract public virtual mixed $both { get; set; } ] + } + + - Methods [0] { + } +} +Class [ abstract class HookedDemo ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [3] { + Property [ abstract public virtual mixed $getOnly { get; } ] + Property [ abstract public virtual mixed $setOnly { set; } ] + Property [ abstract public virtual mixed $both { get; set; } ] + } + + - Methods [0] { + } +} +Class [ class WithHooks ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [3] { + Property [ public virtual mixed $getOnly { get; } ] + Property [ public mixed $setOnly { set; } ] + Property [ public mixed $both { get; set; } ] + } + + - Methods [0] { + } +} +Class [ class WithFinalHooks ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [3] { + Property [ public virtual mixed $getOnly { final get; } ] + Property [ public mixed $setOnly { final set; } ] + Property [ public mixed $both { final get; final set; } ] + } + + - Methods [0] { + } +} +Class [ class WithMixedHooks ] { + @@ %s %d-%d + + - Constants [0] { + } + + - Static properties [0] { + } + + - Static methods [0] { + } + + - Properties [2] { + Property [ public mixed $getIsFinal { final get; set; } ] + Property [ public mixed $setIsFinal { get; final set; } ] + } + + - Methods [0] { + } +} diff --git a/ext/reflection/tests/ReflectionExtension_getDependencies_variation2.phpt b/ext/reflection/tests/ReflectionExtension_getDependencies_variation2.phpt index be13fe27a8202..60527c0b369f2 100644 --- a/ext/reflection/tests/ReflectionExtension_getDependencies_variation2.phpt +++ b/ext/reflection/tests/ReflectionExtension_getDependencies_variation2.phpt @@ -8,7 +8,9 @@ $standard = new ReflectionExtension('standard'); var_dump($standard->getDependencies()); ?> --EXPECTF-- -array(1) { +array(%d) { + ["uri"]=> + %s(8) "Required" ["session"]=> %s(8) "Optional" } diff --git a/ext/reflection/tests/ReflectionMethod_setAccessible.phpt b/ext/reflection/tests/ReflectionMethod_setAccessible.phpt index 92312528a0419..ba4864d28ed86 100644 --- a/ext/reflection/tests/ReflectionMethod_setAccessible.phpt +++ b/ext/reflection/tests/ReflectionMethod_setAccessible.phpt @@ -37,7 +37,7 @@ $protected->invokeArgs(new A, array(NULL)); $protectedStatic->invoke(NULL, NULL); $protectedStatic->invokeArgs(NULL, array(NULL)); ?> ---EXPECT-- +--EXPECTF-- A::aPrivate A::aPrivate A::aPrivateStatic @@ -46,6 +46,14 @@ A::aProtected A::aProtected A::aProtectedStatic A::aProtectedStatic + +Deprecated: Method ReflectionMethod::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionMethod::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionMethod::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionMethod::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d A::aPrivate A::aPrivate A::aPrivateStatic diff --git a/ext/reflection/tests/ReflectionObject_getConstant_basic.phpt b/ext/reflection/tests/ReflectionObject_getConstant_basic.phpt index c132f1121a117..fec75b40eb2a7 100644 --- a/ext/reflection/tests/ReflectionObject_getConstant_basic.phpt +++ b/ext/reflection/tests/ReflectionObject_getConstant_basic.phpt @@ -23,19 +23,31 @@ foreach($classes as $class) { var_dump($rc->getConstant('doesNotexist')); } ?> ---EXPECT-- +--EXPECTF-- Reflecting on instance of class C: string(12) "hello from C" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on instance of class D: string(12) "hello from C" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on instance of class E: string(12) "hello from C" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on instance of class F: string(12) "hello from F" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Reflecting on instance of class X: + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) diff --git a/ext/reflection/tests/ReflectionProperty_getDefaultValue.phpt b/ext/reflection/tests/ReflectionProperty_getDefaultValue.phpt index 423edfe9faf05..d74e1f4bfe6cc 100644 --- a/ext/reflection/tests/ReflectionProperty_getDefaultValue.phpt +++ b/ext/reflection/tests/ReflectionProperty_getDefaultValue.phpt @@ -60,15 +60,21 @@ $property = new ReflectionProperty($test, 'dynamic'); var_dump($property->getDefaultValue()); ?> ---EXPECT-- +--EXPECTF-- NULL string(3) "baz" NULL int(1234) + +Deprecated: ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, use ReflectionProperty::hasDefaultValue() to check if the default value exists in %s on line %d NULL int(1234) + +Deprecated: ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, use ReflectionProperty::hasDefaultValue() to check if the default value exists in %s on line %d NULL NULL int(4) int(42) + +Deprecated: ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, use ReflectionProperty::hasDefaultValue() to check if the default value exists in %s on line %d NULL diff --git a/ext/reflection/tests/ReflectionProperty_getMangledName_basic.phpt b/ext/reflection/tests/ReflectionProperty_getMangledName_basic.phpt new file mode 100644 index 0000000000000..473ac2c84b816 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getMangledName_basic.phpt @@ -0,0 +1,43 @@ +--TEST-- +Test ReflectionProperty::getMangledName() method +--FILE-- +getName() . "\n"; + echo "getMangledName(): " . $reflection->getMangledName() . "\n"; + + $obj = new $class(); + $array = (array) $obj; + echo "In array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "found" : "not found") . "\n"; + echo "\n"; +} + +testMangledName('TestClass', 'publicProp'); +testMangledName('TestClass', 'protectedProp'); +testMangledName('TestClass', 'privateProp'); + +?> +--EXPECTF-- +Property: publicProp +getName(): publicProp +getMangledName(): publicProp +In array cast: found + +Property: protectedProp +getName(): protectedProp +getMangledName(): %0*%0protectedProp +In array cast: found + +Property: privateProp +getName(): privateProp +getMangledName(): %0TestClass%0privateProp +In array cast: found diff --git a/ext/reflection/tests/ReflectionProperty_getMangledName_dynamic.phpt b/ext/reflection/tests/ReflectionProperty_getMangledName_dynamic.phpt new file mode 100644 index 0000000000000..271552ab46aea --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getMangledName_dynamic.phpt @@ -0,0 +1,125 @@ +--TEST-- +Test ReflectionProperty::getMangledName() with dynamic properties +--FILE-- +prop1 = 'value1'; +$stdObj->{'special-name'} = 'special value'; +$stdObj->{'123numeric'} = 'numeric start'; + +function testDynamicProperty($obj, $property, $description) { + try { + $reflection = new ReflectionProperty($obj, $property); + echo "$description:\n"; + echo " getName(): " . $reflection->getName() . "\n"; + echo " getMangledName(): " . $reflection->getMangledName() . "\n"; + + $array = (array) $obj; + echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n"; + echo "\n"; + } catch (ReflectionException $e) { + echo "$description: EXCEPTION - " . $e->getMessage() . "\n\n"; + } +} + +testDynamicProperty($stdObj, 'prop1', 'stdClass property prop1'); +testDynamicProperty($stdObj, 'special-name', 'stdClass property with special name'); +testDynamicProperty($stdObj, '123numeric', 'stdClass property starting with number'); + +echo "=== Testing edge cases ===\n"; +$numericObj = (object)[true]; +testDynamicProperty($numericObj, '0', 'Property name as number'); + +$nullByteObj = (object)["foo\0" => true]; +testDynamicProperty($nullByteObj, "foo\0", 'Property name with null byte'); + +$invalidObj = (object)["::" => true]; +testDynamicProperty($invalidObj, '::', 'Invalid property name'); + +echo "=== Testing regular class with dynamic properties ===\n"; +#[AllowDynamicProperties] +class TestClass { + public $existing = 'existing'; +} + +$obj = new TestClass(); +$obj->dynamic = 'dynamic value'; +$obj->anotherDynamic = 'another dynamic'; + +testDynamicProperty($obj, 'dynamic', 'Regular class dynamic property'); +testDynamicProperty($obj, 'anotherDynamic', 'Regular class another dynamic property'); + +$reflection = new ReflectionProperty($obj, 'existing'); +echo "Regular property:\n"; +echo " getName(): " . $reflection->getName() . "\n"; +echo " getMangledName(): " . $reflection->getMangledName() . "\n"; + +echo "\n=== Testing ReflectionProperty from class vs instance ===\n"; +try { + $reflection = new ReflectionProperty('TestClass', 'dynamic'); + echo "This should not be reached\n"; +} catch (ReflectionException $e) { + echo "Expected exception for class-based reflection: " . $e->getMessage() . "\n"; +} + +try { + $reflection = new ReflectionProperty($obj, 'dynamic'); + echo "Instance-based reflection works: " . $reflection->getMangledName() . "\n"; +} catch (ReflectionException $e) { + echo "Unexpected exception: " . $e->getMessage() . "\n"; +} + +?> +--EXPECTF-- +=== Testing stdClass with dynamic properties === +stdClass property prop1: + getName(): prop1 + getMangledName(): prop1 + Found in array cast: yes + +stdClass property with special name: + getName(): special-name + getMangledName(): special-name + Found in array cast: yes + +stdClass property starting with number: + getName(): 123numeric + getMangledName(): 123numeric + Found in array cast: yes + +=== Testing edge cases === +Property name as number: + getName(): 0 + getMangledName(): 0 + Found in array cast: yes + +Property name with null byte: + getName(): foo%0 + getMangledName(): foo%0 + Found in array cast: yes + +Invalid property name: + getName(): :: + getMangledName(): :: + Found in array cast: yes + +=== Testing regular class with dynamic properties === +Regular class dynamic property: + getName(): dynamic + getMangledName(): dynamic + Found in array cast: yes + +Regular class another dynamic property: + getName(): anotherDynamic + getMangledName(): anotherDynamic + Found in array cast: yes + +Regular property: + getName(): existing + getMangledName(): existing + +=== Testing ReflectionProperty from class vs instance === +Expected exception for class-based reflection: Property TestClass::$dynamic does not exist +Instance-based reflection works: dynamic diff --git a/ext/reflection/tests/ReflectionProperty_getMangledName_hooks.phpt b/ext/reflection/tests/ReflectionProperty_getMangledName_hooks.phpt new file mode 100644 index 0000000000000..da00a0da2912e --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getMangledName_hooks.phpt @@ -0,0 +1,82 @@ +--TEST-- +Test ReflectionProperty::getMangledName() with property hooks +--FILE-- + "virtual"; + } + + public string $bar { + get => "hooked getter"; + set => throw new Exception("Cannot set bar"); + } + + public string $baz = "backed"; +} + +$d = new Demo(); + +function testHookedProperty($obj, $property, $description) { + try { + $reflection = new ReflectionProperty($obj, $property); + echo "$description:\n"; + echo " getName(): " . $reflection->getName() . "\n"; + echo " getMangledName(): " . $reflection->getMangledName() . "\n"; + + $array = (array) $obj; + echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n"; + echo " Has hooks: " . ($reflection->hasHooks() ? "yes" : "no") . "\n"; + echo "\n"; + } catch (ReflectionException $e) { + echo "$description: EXCEPTION - " . $e->getMessage() . "\n\n"; + } +} + +testHookedProperty($d, 'foo', 'Virtual hooked property (protected)'); +testHookedProperty($d, 'bar', 'Hooked property with getter/setter (public)'); +testHookedProperty($d, 'baz', 'Regular backed property'); + +echo "=== Object dump ===\n"; +var_dump($d); + +echo "\n=== Array cast ===\n"; +var_dump((array)$d); + +?> +--EXPECTF-- +=== Testing virtual hooked properties === +Virtual hooked property (protected): + getName(): foo + getMangledName(): %0*%0foo + Found in array cast: no + Has hooks: yes + +Hooked property with getter/setter (public): + getName(): bar + getMangledName(): bar + Found in array cast: no + Has hooks: yes + +Regular backed property: + getName(): baz + getMangledName(): baz + Found in array cast: yes + Has hooks: no + +=== Object dump === +object(Demo)#1 (1) { + ["bar"]=> + uninitialized(string) + ["baz"]=> + string(6) "backed" +} + +=== Array cast === +array(1) { + ["baz"]=> + string(6) "backed" +} diff --git a/ext/reflection/tests/ReflectionProperty_getMangledName_inheritance.phpt b/ext/reflection/tests/ReflectionProperty_getMangledName_inheritance.phpt new file mode 100644 index 0000000000000..301756c8cbf2b --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getMangledName_inheritance.phpt @@ -0,0 +1,87 @@ +--TEST-- +Test ReflectionProperty::getMangledName() with inheritance +--FILE-- +getMangledName() . "'\n"; + echo "Key exists in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n"; + echo "\n"; +} + +testProperty('ParentClass', 'public'); +testProperty('ParentClass', 'protected'); +testProperty('ParentClass', 'private'); + +testProperty('ChildClass', 'public'); +testProperty('ChildClass', 'protected'); +testProperty('ChildClass', 'childProp'); +testProperty('ChildClass', 'private'); + +echo "Access to parent's private property not in child:\n"; + +try { + $reflection = new ReflectionProperty('ChildClass', 'parentOnly'); + echo "ERROR: Should have failed\n"; +} catch (ReflectionException $e) { + echo "Instance-based creation failed as expected: " . $e->getMessage() . "\n"; +} + +try { + $obj = new ChildClass(); + $reflection = new ReflectionProperty($obj, 'parentOnly'); + echo "ERROR: Should have failed\n"; +} catch (ReflectionException $e) { + echo "Object-based creation failed as expected: " . $e->getMessage() . "\n"; +} + +?> +--EXPECTF-- +Class: ParentClass, Property: $public +Mangled name: 'public' +Key exists in array cast: yes + +Class: ParentClass, Property: $protected +Mangled name: '%0*%0protected' +Key exists in array cast: yes + +Class: ParentClass, Property: $private +Mangled name: '%0ParentClass%0private' +Key exists in array cast: yes + +Class: ChildClass, Property: $public +Mangled name: 'public' +Key exists in array cast: yes + +Class: ChildClass, Property: $protected +Mangled name: '%0*%0protected' +Key exists in array cast: yes + +Class: ChildClass, Property: $childProp +Mangled name: '%0*%0childProp' +Key exists in array cast: yes + +Class: ChildClass, Property: $private +Mangled name: '%0ChildClass%0private' +Key exists in array cast: yes + +Access to parent's private property not in child: +Instance-based creation failed as expected: Property ChildClass::$parentOnly does not exist +Object-based creation failed as expected: Property ChildClass::$parentOnly does not exist diff --git a/ext/reflection/tests/ReflectionProperty_getMangledName_instance.phpt b/ext/reflection/tests/ReflectionProperty_getMangledName_instance.phpt new file mode 100644 index 0000000000000..7c24ce85f1734 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getMangledName_instance.phpt @@ -0,0 +1,99 @@ +--TEST-- +Test ReflectionProperty::getMangledName() from instance vs class +--FILE-- +dynamic = 'dynamic'; + +echo "=== Testing ReflectionProperty from CLASS ===\n"; + +function testFromClass($property) { + try { + $reflection = new ReflectionProperty('TestClass', $property); + echo "Property $property from class:\n"; + echo " getName(): " . $reflection->getName() . "\n"; + echo " getMangledName(): " . $reflection->getMangledName() . "\n"; + echo "\n"; + } catch (ReflectionException $e) { + echo "Property $property from class: EXCEPTION - " . $e->getMessage() . "\n\n"; + } +} + +testFromClass('public'); +testFromClass('protected'); +testFromClass('private'); +testFromClass('dynamic'); + +echo "=== Testing ReflectionProperty from INSTANCE ===\n"; + +function testFromInstance($obj, $property) { + try { + $reflection = new ReflectionProperty($obj, $property); + echo "Property $property from instance:\n"; + echo " getName(): " . $reflection->getName() . "\n"; + echo " getMangledName(): " . $reflection->getMangledName() . "\n"; + + $array = (array) $obj; + echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n"; + echo "\n"; + } catch (ReflectionException $e) { + echo "Property $property from instance: EXCEPTION - " . $e->getMessage() . "\n\n"; + } +} + +testFromInstance($obj, 'public'); +testFromInstance($obj, 'protected'); +testFromInstance($obj, 'private'); + +echo "=== Instance array keys ===\n"; +$array = (array) $obj; +foreach (array_keys($array) as $key) { + echo "Key: '$key'\n"; +} + +?> +--EXPECTF-- +=== Testing ReflectionProperty from CLASS === +Property public from class: + getName(): public + getMangledName(): public + +Property protected from class: + getName(): protected + getMangledName(): %0*%0protected + +Property private from class: + getName(): private + getMangledName(): %0TestClass%0private + +Property dynamic from class: EXCEPTION - Property TestClass::$dynamic does not exist + +=== Testing ReflectionProperty from INSTANCE === +Property public from instance: + getName(): public + getMangledName(): public + Found in array cast: yes + +Property protected from instance: + getName(): protected + getMangledName(): %0*%0protected + Found in array cast: yes + +Property private from instance: + getName(): private + getMangledName(): %0TestClass%0private + Found in array cast: yes + +=== Instance array keys === +Key: 'public' +Key: '%0*%0protected' +Key: '%0TestClass%0private' +Key: 'dynamic' diff --git a/ext/reflection/tests/ReflectionProperty_getMangledName_override.phpt b/ext/reflection/tests/ReflectionProperty_getMangledName_override.phpt new file mode 100644 index 0000000000000..3f6a3bfdcc5e8 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_getMangledName_override.phpt @@ -0,0 +1,123 @@ +--TEST-- +Test ReflectionProperty::getMangledName() with property overrides and visibility changes +--FILE-- +getName() . "\n"; + echo " getMangledName(): " . $reflection->getMangledName() . "\n"; + echo " Visibility: " . ($reflection->isPublic() ? 'public' : ($reflection->isProtected() ? 'protected' : 'private')) . "\n"; + + $obj = new $class(); + $array = (array) $obj; + echo " Found in array cast: " . (array_key_exists($reflection->getMangledName(), $array) ? "yes" : "no") . "\n"; + echo "\n"; +} + +testPropertyOverride('Parent1', 'prop', 'Parent public property'); +testPropertyOverride('Child1', 'prop', 'Child public property (overrides parent public)'); + +testPropertyOverride('Parent1', 'protectedProp', 'Parent protected property'); +testPropertyOverride('Child1', 'protectedProp', 'Child public property (overrides parent protected)'); + +testPropertyOverride('Parent2', 'visibilityTest', 'Parent protected property'); +testPropertyOverride('Child2', 'visibilityTest', 'Child public property (overrides parent protected)'); + +testPropertyOverride('Parent1', 'privateProp', 'Parent private property'); + +echo "Child1 instance array keys:\n"; +$child1 = new Child1(); +$array = (array) $child1; +foreach (array_keys($array) as $key) { + echo " '$key'\n"; +} + +?> +--EXPECTF-- +Parent public property: + Class: Parent1 + Property: prop + getName(): prop + getMangledName(): prop + Visibility: public + Found in array cast: yes + +Child public property (overrides parent public): + Class: Child1 + Property: prop + getName(): prop + getMangledName(): prop + Visibility: public + Found in array cast: yes + +Parent protected property: + Class: Parent1 + Property: protectedProp + getName(): protectedProp + getMangledName(): %0*%0protectedProp + Visibility: protected + Found in array cast: yes + +Child public property (overrides parent protected): + Class: Child1 + Property: protectedProp + getName(): protectedProp + getMangledName(): protectedProp + Visibility: public + Found in array cast: yes + +Parent protected property: + Class: Parent2 + Property: visibilityTest + getName(): visibilityTest + getMangledName(): %0*%0visibilityTest + Visibility: protected + Found in array cast: yes + +Child public property (overrides parent protected): + Class: Child2 + Property: visibilityTest + getName(): visibilityTest + getMangledName(): visibilityTest + Visibility: public + Found in array cast: yes + +Parent private property: + Class: Parent1 + Property: privateProp + getName(): privateProp + getMangledName(): %0Parent1%0privateProp + Visibility: private + Found in array cast: yes + +Child1 instance array keys: + 'prop' + 'protectedProp' + '%0Parent1%0privateProp' diff --git a/ext/reflection/tests/ReflectionProperty_setAccessible.phpt b/ext/reflection/tests/ReflectionProperty_setAccessible.phpt index 4e12af87916fa..b63ab38c15981 100644 --- a/ext/reflection/tests/ReflectionProperty_setAccessible.phpt +++ b/ext/reflection/tests/ReflectionProperty_setAccessible.phpt @@ -95,6 +95,14 @@ string(1) "e" string(1) "f" string(1) "g" string(1) "h" + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d string(1) "e" string(1) "f" string(1) "g" @@ -111,6 +119,12 @@ string(1) "c" string(1) "e" string(1) "f" string(1) "g" + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d + +Deprecated: Method ReflectionProperty::setAccessible() is deprecated since 8.5, as it has no effect in %s on line %d string(1) "e" string(1) "f" string(1) "g" diff --git a/ext/reflection/tests/ReflectionProperty_toString_001.phpt b/ext/reflection/tests/ReflectionProperty_toString_001.phpt new file mode 100644 index 0000000000000..0af0283bb5069 --- /dev/null +++ b/ext/reflection/tests/ReflectionProperty_toString_001.phpt @@ -0,0 +1,89 @@ +--TEST-- +Using ReflectionProperty::__toString() with hooked properties (GH-17927) +--FILE-- + "always this string"; + } + public mixed $setOnly { + set => strtolower($value); + } + public mixed $both { + get => $this->prop3; + set => strtolower($value); + } +} +class WithFinalHooks { + public mixed $getOnly { + final get => "always this string"; + } + public mixed $setOnly { + final set => strtolower($value); + } + public mixed $both { + final get => $this->prop3; + final set => strtolower($value); + } +} +class WithMixedHooks { + public mixed $getIsFinal { + final get => "always this string"; + set => strtolower($value); + } + public mixed $setIsFinal { + get => $this->setIsFinal; + final set => strtolower($value); + } +} +$classes = [ + IHookedDemo::class, + HookedDemo::class, + WithHooks::class, + WithFinalHooks::class, + WithMixedHooks::class, +]; +foreach ( $classes as $clazz ) { + echo "$clazz:\n"; + $ref = new ReflectionClass( $clazz ); + foreach ( $ref->getProperties() as $prop ) { + echo $prop; + } + echo "\n"; +} +?> +--EXPECT-- +IHookedDemo: +Property [ abstract public virtual mixed $getOnly { get; } ] +Property [ abstract public virtual mixed $setOnly { set; } ] +Property [ abstract public virtual mixed $both { get; set; } ] + +HookedDemo: +Property [ abstract public virtual mixed $getOnly { get; } ] +Property [ abstract public virtual mixed $setOnly { set; } ] +Property [ abstract public virtual mixed $both { get; set; } ] + +WithHooks: +Property [ public virtual mixed $getOnly { get; } ] +Property [ public mixed $setOnly { set; } ] +Property [ public mixed $both { get; set; } ] + +WithFinalHooks: +Property [ public virtual mixed $getOnly { final get; } ] +Property [ public mixed $setOnly { final set; } ] +Property [ public mixed $both { final get; final set; } ] + +WithMixedHooks: +Property [ public mixed $getIsFinal { final get; set; } ] +Property [ public mixed $setIsFinal { get; final set; } ] diff --git a/ext/reflection/tests/Reflection_getModifierNames_001.phpt b/ext/reflection/tests/Reflection_getModifierNames_001.phpt index 918ef2f28000a..78ba327df6f54 100644 --- a/ext/reflection/tests/Reflection_getModifierNames_001.phpt +++ b/ext/reflection/tests/Reflection_getModifierNames_001.phpt @@ -15,6 +15,8 @@ printModifiers(ReflectionMethod::IS_ABSTRACT | ReflectionMethod::IS_FINAL); printModifiers(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_STATIC | ReflectionProperty::IS_READONLY); printModifiers(ReflectionClass::IS_READONLY); printModifiers(ReflectionProperty::IS_VIRTUAL); +printModifiers(ReflectionProperty::IS_PROTECTED_SET); +printModifiers(ReflectionProperty::IS_PRIVATE_SET); ?> --EXPECT-- private @@ -25,3 +27,5 @@ abstract,final public,static,readonly readonly virtual +protected(set) +private(set) diff --git a/ext/reflection/tests/abstract_property_indicated.phpt b/ext/reflection/tests/abstract_property_indicated.phpt index a70d88b7ece29..23866be890d5b 100644 --- a/ext/reflection/tests/abstract_property_indicated.phpt +++ b/ext/reflection/tests/abstract_property_indicated.phpt @@ -31,12 +31,12 @@ Class [ abstract class Demo ] { } - Properties [2] { - Property [ abstract public $a ] + Property [ abstract public virtual $a { get; } ] Property [ public $b = NULL ] } - Methods [0] { } } -Property [ abstract public $a ] +Property [ abstract public virtual $a { get; } ] Property [ public $b = NULL ] diff --git a/ext/reflection/tests/bug38653.phpt b/ext/reflection/tests/bug38653.phpt index 36504e7c7b66c..e166546eeb9a0 100644 --- a/ext/reflection/tests/bug38653.phpt +++ b/ext/reflection/tests/bug38653.phpt @@ -20,9 +20,11 @@ var_dump($foo->getConstant("no such const")); echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- int(10) string(0) "" string(4) "test" + +Deprecated: ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists in %s on line %d bool(false) Done diff --git a/ext/reflection/tests/bug79683.phpt b/ext/reflection/tests/bug79683.phpt index 766571918afb6..4eeafb6bb9308 100644 --- a/ext/reflection/tests/bug79683.phpt +++ b/ext/reflection/tests/bug79683.phpt @@ -22,7 +22,6 @@ $b = new B(); $reflector = new ReflectionClass($b); $property = $reflector->getProperty('prop2'); -$property->setAccessible(true); $property->setValue($b, new A()); var_dump($b); diff --git a/ext/reflection/tests/gh18373.phpt b/ext/reflection/tests/gh18373.phpt new file mode 100644 index 0000000000000..30aa1a0f5fe54 --- /dev/null +++ b/ext/reflection/tests/gh18373.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-18373: Don't substitute self/parent with anonymous class +--FILE-- +getMethod('test')->getReturnType()->getName(), "\n"; + +?> +--EXPECT-- +self diff --git a/ext/reflection/tests/gh19187.phpt b/ext/reflection/tests/gh19187.phpt new file mode 100644 index 0000000000000..35a684aa6af73 --- /dev/null +++ b/ext/reflection/tests/gh19187.phpt @@ -0,0 +1,56 @@ +--TEST-- +GH-19187: ReflectionNamedType::getName() should not include nullable type +--FILE-- + $value; + } + public string|null $b { + set(string|null $value) => $value; + } + public string|null $c { + get => $this->c; + } +} + +foreach ((new ReflectionClass(C::class))->getProperties() as $r) { + $type = $r->getType(); + echo $type, "\n"; + echo $type->getName(), "\n"; + var_dump($type->allowsNull()); + echo "\n"; + + $settableType = $r->getSettableType(); + echo $settableType, "\n"; + echo $settableType->getName(), "\n"; + var_dump($settableType->allowsNull()); + echo "\n"; +} + +?> +--EXPECT-- +?string +string +bool(true) + +?string +string +bool(true) + +?string +string +bool(true) + +?string +string +bool(true) + +?string +string +bool(true) + +?string +string +bool(true) diff --git a/ext/reflection/tests/internal_parameter_default_value/check_all.phpt b/ext/reflection/tests/internal_parameter_default_value/check_all.phpt index 534f781c4fc1a..241dea449b615 100644 --- a/ext/reflection/tests/internal_parameter_default_value/check_all.phpt +++ b/ext/reflection/tests/internal_parameter_default_value/check_all.phpt @@ -30,7 +30,7 @@ foreach (get_declared_classes() as $class) { ?> ===DONE=== --EXPECTF-- -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d -Deprecated: Constant SUNFUNCS_RET_STRING is deprecated in %s on line %d +Deprecated: Constant SUNFUNCS_RET_STRING is deprecated since 8.4, as date_sunrise() and date_sunset() were deprecated in 8.1 in %s on line %d ===DONE=== diff --git a/ext/reflection/tests/property_hooks/basics.phpt b/ext/reflection/tests/property_hooks/basics.phpt index 8c363dcc4bfb0..6011018c64cfa 100644 --- a/ext/reflection/tests/property_hooks/basics.phpt +++ b/ext/reflection/tests/property_hooks/basics.phpt @@ -47,7 +47,6 @@ try { } catch (ReflectionException $e) { echo $e->getMessage(), "\n"; } -$s->setAccessible(true); $s->invoke($test, 42); var_dump($test->prop2); dumpFlags($rp2); diff --git a/ext/session/php_session.h b/ext/session/php_session.h index dfa7632e5a447..e48ed4615297f 100644 --- a/ext/session/php_session.h +++ b/ext/session/php_session.h @@ -120,7 +120,6 @@ typedef enum { } php_session_status; typedef struct _php_session_rfc1867_progress { - size_t sname_len; zval sid; smart_str key; @@ -139,17 +138,18 @@ typedef struct _php_session_rfc1867_progress { } php_session_rfc1867_progress; typedef struct _php_ps_globals { - char *save_path; - char *session_name; + zend_string *save_path; + zend_string *session_name; zend_string *id; char *extern_referer_chk; - char *cache_limiter; + zend_string *cache_limiter; zend_long cookie_lifetime; - char *cookie_path; - char *cookie_domain; - char *cookie_samesite; + zend_string *cookie_path; + zend_string *cookie_domain; + zend_string *cookie_samesite; bool cookie_secure; bool cookie_httponly; + bool cookie_partitioned; const ps_module *mod; const ps_module *default_mod; void *mod_data; @@ -191,8 +191,8 @@ typedef struct _php_ps_globals { zend_long sid_bits_per_character; php_session_rfc1867_progress *rfc1867_progress; - char *rfc1867_prefix; /* session.upload_progress.prefix */ - char *rfc1867_name; /* session.upload_progress.name */ + zend_string *rfc1867_prefix; /* session.upload_progress.prefix */ + zend_string *rfc1867_name; /* session.upload_progress.name */ zend_long rfc1867_freq; /* session.upload_progress.freq */ double rfc1867_min_freq; /* session.upload_progress.min_freq */ bool rfc1867_enabled; /* session.upload_progress.enabled */ diff --git a/ext/session/session.c b/ext/session/session.c index 7b677249fb41b..489f82d6f142f 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -54,6 +54,8 @@ #include "mod_mm.h" #endif +#include "zend_attributes.h" + PHPAPI ZEND_DECLARE_MODULE_GLOBALS(ps) static zend_result php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra); @@ -100,6 +102,7 @@ zend_class_entry *php_session_update_timestamp_iface_entry; static zend_result php_session_send_cookie(void); static zend_result php_session_abort(void); +static void proposed_session_id_to_session_id(zval *proposed_session_id); /* Initialized in MINIT, readonly otherwise. */ static int my_module_number = 0; @@ -367,7 +370,7 @@ PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS) * ps_modules appropriately */ PHPAPI zend_result php_session_valid_key(const char *key) { - size_t len; + size_t key_len; const char *p; char c; @@ -382,11 +385,11 @@ PHPAPI zend_result php_session_valid_key(const char *key) } } - len = p - key; + key_len = p - key; /* Somewhat arbitrary length limit here, but should be way more than anyone needs and avoids file-level warnings later on if we exceed MAX_PATH */ - if (len == 0 || len > PS_MAX_SID_LENGTH) { + if (key_len == 0 || key_len > PS_MAX_SID_LENGTH) { return FAILURE; } @@ -396,20 +399,21 @@ PHPAPI zend_result php_session_valid_key(const char *key) static zend_long php_session_gc(bool immediate) { - zend_long num = -1; + zend_long sessions_deleted = -1; bool collect = immediate; /* GC must be done before reading session data. */ if ((PS(mod_data) || PS(mod_user_implemented))) { + /* Use probability-based GC if not forced and probability is configured */ if (!collect && PS(gc_probability) > 0) { collect = php_random_range(PS(random), 0, PS(gc_divisor) - 1) < PS(gc_probability); } if (collect) { - PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &num); + PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &sessions_deleted); } } - return num; + return sessions_deleted; } static zend_result php_session_initialize(void) @@ -425,12 +429,12 @@ static zend_result php_session_initialize(void) } /* Open session handler first */ - if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE + if (PS(mod)->s_open(&PS(mod_data), ZSTR_VAL(PS(save_path)), ZSTR_VAL(PS(session_name))) == FAILURE /* || PS(mod_data) == NULL */ /* FIXME: open must set valid PS(mod_data) with success */ ) { php_session_abort(); if (!EG(exception)) { - php_error_docref(NULL, E_WARNING, "Failed to initialize storage module: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_WARNING, "Failed to initialize storage module: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } return FAILURE; } @@ -444,7 +448,7 @@ static zend_result php_session_initialize(void) if (!PS(id)) { php_session_abort(); if (!EG(exception)) { - zend_throw_error(NULL, "Failed to create session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + zend_throw_error(NULL, "Failed to create session ID: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } return FAILURE; } @@ -477,7 +481,7 @@ static zend_result php_session_initialize(void) php_session_abort(); /* FYI: Some broken save handlers return FAILURE for non-existent session ID, this is incorrect */ if (!EG(exception)) { - php_error_docref(NULL, E_WARNING, "Failed to read session data: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_WARNING, "Failed to read session data: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } return FAILURE; } @@ -513,7 +517,7 @@ static void php_session_save_current_state(int write) if (write) { IF_SESSION_VARS() { zend_string *handler_class_name = PS(mod_user_class_name); - const char *handler_function_name; + const char *handler_function_name = "write"; if (PS(mod_data) || PS(mod_user_implemented)) { zend_string *val; @@ -529,12 +533,10 @@ static void php_session_save_current_state(int write) handler_function_name = handler_class_name != NULL ? "updateTimestamp" : "update_timestamp"; } else { ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, PS(gc_maxlifetime)); - handler_function_name = "write"; } zend_string_release_ex(val, 0); } else { ret = PS(mod)->s_write(&PS(mod_data), PS(id), ZSTR_EMPTY_ALLOC(), PS(gc_maxlifetime)); - handler_function_name = "write"; } } @@ -544,14 +546,14 @@ static void php_session_save_current_state(int write) "verify that the current setting of session.save_path " "is correct (%s)", PS(mod)->s_name, - PS(save_path)); + ZSTR_VAL(PS(save_path))); } else if (handler_class_name != NULL) { php_error_docref(NULL, E_WARNING, "Failed to write session data using user " - "defined save handler. (session.save_path: %s, handler: %s::%s)", PS(save_path), + "defined save handler. (session.save_path: %s, handler: %s::%s)", ZSTR_VAL(PS(save_path)), ZSTR_VAL(handler_class_name), handler_function_name); } else { php_error_docref(NULL, E_WARNING, "Failed to write session data using user " - "defined save handler. (session.save_path: %s, handler: %s)", PS(save_path), + "defined save handler. (session.save_path: %s, handler: %s)", ZSTR_VAL(PS(save_path)), handler_function_name); } } @@ -651,7 +653,7 @@ static PHP_INI_MH(OnUpdateSaveDir) SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; - /* Only do the safemode/open_basedir check at runtime */ + /* Only do the open_basedir check at runtime */ if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) { char *p; @@ -675,7 +677,7 @@ static PHP_INI_MH(OnUpdateSaveDir) } } - return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + return OnUpdateStr(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } @@ -706,7 +708,7 @@ static PHP_INI_MH(OnUpdateName) return FAILURE; } - return OnUpdateStringUnempty(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + return OnUpdateStrNotEmpty(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } @@ -738,11 +740,11 @@ static PHP_INI_MH(OnUpdateSessionLong) return OnUpdateLong(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } -static PHP_INI_MH(OnUpdateSessionString) +static PHP_INI_MH(OnUpdateSessionStr) { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; - return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + return OnUpdateStr(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } @@ -888,30 +890,31 @@ static PHP_INI_MH(OnUpdateRefererCheck) } PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir, save_path, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateName, session_name, php_ps_globals, ps_globals) - PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler) - STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_PERDIR, OnUpdateBool, auto_start, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateSessionGcProbability, gc_probability, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateSessionDivisor,gc_divisor, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.gc_maxlifetime", "1440", PHP_INI_ALL, OnUpdateSessionLong, gc_maxlifetime, php_ps_globals, ps_globals) - PHP_INI_ENTRY("session.serialize_handler", "php", PHP_INI_ALL, OnUpdateSerializer) - STD_PHP_INI_ENTRY("session.cookie_lifetime", "0", PHP_INI_ALL, OnUpdateCookieLifetime,cookie_lifetime, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cookie_path", "/", PHP_INI_ALL, OnUpdateSessionString, cookie_path, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateSessionString, cookie_domain, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionString, cookie_samesite, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateUseOnlyCookies, use_only_cookies, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateRefererCheck, extern_referer_chk, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateSessionString, cache_limiter, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateSessionLong, cache_expire, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.use_trans_sid", "0", PHP_INI_ALL, OnUpdateUseTransSid, use_trans_sid, php_ps_globals, ps_globals) - PHP_INI_ENTRY("session.sid_length", "32", PHP_INI_ALL, OnUpdateSidLength) - PHP_INI_ENTRY("session.sid_bits_per_character", "4", PHP_INI_ALL, OnUpdateSidBits) - STD_PHP_INI_BOOLEAN("session.lazy_write", "1", PHP_INI_ALL, OnUpdateSessionBool, lazy_write, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir, save_path, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateName, session_name, php_ps_globals, ps_globals) + PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler) + STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_PERDIR, OnUpdateBool, auto_start, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateSessionGcProbability, gc_probability, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateSessionDivisor, gc_divisor, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.gc_maxlifetime", "1440", PHP_INI_ALL, OnUpdateSessionLong, gc_maxlifetime, php_ps_globals, ps_globals) + PHP_INI_ENTRY("session.serialize_handler", "php", PHP_INI_ALL, OnUpdateSerializer) + STD_PHP_INI_ENTRY("session.cookie_lifetime", "0", PHP_INI_ALL, OnUpdateCookieLifetime, cookie_lifetime, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cookie_path", "/", PHP_INI_ALL, OnUpdateSessionStr, cookie_path, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_domain, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.cookie_partitioned", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_partitioned, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_samesite, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateUseOnlyCookies, use_only_cookies, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateRefererCheck, extern_referer_chk, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateSessionStr, cache_limiter, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateSessionLong, cache_expire, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.use_trans_sid", "0", PHP_INI_ALL, OnUpdateUseTransSid, use_trans_sid, php_ps_globals, ps_globals) + PHP_INI_ENTRY("session.sid_length", "32", PHP_INI_ALL, OnUpdateSidLength) + PHP_INI_ENTRY("session.sid_bits_per_character", "4", PHP_INI_ALL, OnUpdateSidBits) + STD_PHP_INI_BOOLEAN("session.lazy_write", "1", PHP_INI_ALL, OnUpdateSessionBool, lazy_write, php_ps_globals, ps_globals) /* Upload progress */ STD_PHP_INI_BOOLEAN("session.upload_progress.enabled", @@ -919,9 +922,9 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("session.upload_progress.cleanup", "1", ZEND_INI_PERDIR, OnUpdateBool, rfc1867_cleanup, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.upload_progress.prefix", - "upload_progress_", ZEND_INI_PERDIR, OnUpdateString, rfc1867_prefix, php_ps_globals, ps_globals) + "upload_progress_", ZEND_INI_PERDIR, OnUpdateStr, rfc1867_prefix, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.upload_progress.name", - "PHP_SESSION_UPLOAD_PROGRESS", ZEND_INI_PERDIR, OnUpdateString, rfc1867_name, php_ps_globals, ps_globals) + "PHP_SESSION_UPLOAD_PROGRESS", ZEND_INI_PERDIR, OnUpdateStr, rfc1867_name, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.upload_progress.freq", "1%", ZEND_INI_PERDIR, OnUpdateRfc1867Freq, rfc1867_freq, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.upload_progress.min_freq", "1", ZEND_INI_PERDIR, OnUpdateReal, rfc1867_min_freq,php_ps_globals, ps_globals) @@ -992,7 +995,7 @@ PS_SERIALIZER_ENCODE_FUNC(php_binary) PS_ENCODE_LOOP( if (ZSTR_LEN(key) > PS_BIN_MAX) continue; smart_str_appendc(&buf, (unsigned char)ZSTR_LEN(key)); - smart_str_appendl(&buf, ZSTR_VAL(key), ZSTR_LEN(key)); + smart_str_append(&buf, key); php_var_serialize(&buf, struc, &var_hash); ); @@ -1054,7 +1057,7 @@ PS_SERIALIZER_ENCODE_FUNC(php) PHP_VAR_SERIALIZE_INIT(var_hash); PS_ENCODE_LOOP( - smart_str_appendl(&buf, ZSTR_VAL(key), ZSTR_LEN(key)); + smart_str_append(&buf, key); if (memchr(ZSTR_VAL(key), PS_DELIMITER, ZSTR_LEN(key))) { PHP_VAR_SERIALIZE_DESTROY(var_hash); smart_str_free(&buf); @@ -1164,7 +1167,7 @@ static const ps_module *ps_modules[MAX_MODULES + 1] = { PHPAPI zend_result php_session_register_module(const ps_module *ptr) { - int ret = FAILURE; + zend_result ret = FAILURE; for (int i = 0; i < MAX_MODULES; i++) { if (!ps_modules[i]) { @@ -1213,7 +1216,7 @@ static const char *week_days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; -static inline void strcpy_gmt(char *ubuf, time_t *when) +static inline void strcpy_gmt(char *ubuf, const time_t *when) { char buf[MAX_STR]; struct tm tm, *res; @@ -1312,7 +1315,9 @@ static int php_session_cache_limiter(void) { const php_session_cache_limiter_t *lim; - if (PS(cache_limiter)[0] == '\0') return 0; + if (ZSTR_LEN(PS(cache_limiter)) == 0) { + return 0; + } if (PS(session_status) != php_session_active) return -1; if (SG(headers_sent)) { @@ -1322,7 +1327,7 @@ static int php_session_cache_limiter(void) } for (lim = php_session_cache_limiters; lim->name; lim++) { - if (!strcasecmp(lim->name, PS(cache_limiter))) { + if (!strcasecmp(lim->name, ZSTR_VAL(PS(cache_limiter)))) { lim->func(); return 0; } @@ -1335,46 +1340,19 @@ static int php_session_cache_limiter(void) * Cookie Management * ********************* */ -/* - * Remove already sent session ID cookie. - * It must be directly removed from SG(sapi_header) because sapi_add_header_ex() - * removes all of matching cookie. i.e. It deletes all of Set-Cookie headers. - */ static void php_session_remove_cookie(void) { - sapi_header_struct *header; - zend_llist *l = &SG(sapi_headers).headers; - zend_llist_element *next; - zend_llist_element *current; char *session_cookie; size_t session_cookie_len; - size_t len = sizeof("Set-Cookie")-1; - - ZEND_ASSERT(strpbrk(PS(session_name), SESSION_FORBIDDEN_CHARS) == NULL); - spprintf(&session_cookie, 0, "Set-Cookie: %s=", PS(session_name)); - - session_cookie_len = strlen(session_cookie); - current = l->head; - while (current) { - header = (sapi_header_struct *)(current->data); - next = current->next; - if (header->header_len > len && header->header[len] == ':' - && !strncmp(header->header, session_cookie, session_cookie_len)) { - if (current->prev) { - current->prev->next = next; - } else { - l->head = next; - } - if (next) { - next->prev = current->prev; - } else { - l->tail = current->prev; - } - sapi_free_header(header); - efree(current); - --l->count; - } - current = next; - } + sapi_header_line header_line = {0}; + + ZEND_ASSERT(strpbrk(ZSTR_VAL(PS(session_name)), SESSION_FORBIDDEN_CHARS) == NULL); + session_cookie_len = spprintf(&session_cookie, 0, "Set-Cookie: %s=", ZSTR_VAL(PS(session_name))); + + header_line.line = session_cookie; + header_line.line_len = session_cookie_len; + header_line.header_len = sizeof("Set-Cookie") - 1; + sapi_header_op(SAPI_HEADER_DELETE_PREFIX, &header_line); + efree(session_cookie); } @@ -1389,15 +1367,21 @@ static zend_result php_session_send_cookie(void) return FAILURE; } - ZEND_ASSERT(strpbrk(PS(session_name), SESSION_FORBIDDEN_CHARS) == NULL); + /* Check for invalid settings combinations */ + if (UNEXPECTED(PS(cookie_partitioned) && !PS(cookie_secure))) { + php_error_docref(NULL, E_WARNING, "Partitioned session cookie cannot be used without also configuring it as secure"); + return FAILURE; + } + + ZEND_ASSERT(strpbrk(ZSTR_VAL(PS(session_name)), SESSION_FORBIDDEN_CHARS) == NULL); /* URL encode id because it might be user supplied */ e_id = php_url_encode(ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id))); - smart_str_appendl(&ncookie, "Set-Cookie: ", sizeof("Set-Cookie: ")-1); - smart_str_appendl(&ncookie, PS(session_name), strlen(PS(session_name))); + smart_str_appends(&ncookie, "Set-Cookie: "); + smart_str_append(&ncookie, PS(session_name)); smart_str_appendc(&ncookie, '='); - smart_str_appendl(&ncookie, ZSTR_VAL(e_id), ZSTR_LEN(e_id)); + smart_str_append(&ncookie, e_id); zend_string_release_ex(e_id, 0); @@ -1409,9 +1393,9 @@ static zend_result php_session_send_cookie(void) t = tv.tv_sec + PS(cookie_lifetime); if (t > 0) { - date_fmt = php_format_date("D, d M Y H:i:s \\G\\M\\T", sizeof("D, d M Y H:i:s \\G\\M\\T")-1, t, 0); + date_fmt = php_format_date(ZEND_STRL("D, d M Y H:i:s \\G\\M\\T"), t, false); smart_str_appends(&ncookie, COOKIE_EXPIRES); - smart_str_appendl(&ncookie, ZSTR_VAL(date_fmt), ZSTR_LEN(date_fmt)); + smart_str_append(&ncookie, date_fmt); zend_string_release_ex(date_fmt, 0); smart_str_appends(&ncookie, COOKIE_MAX_AGE); @@ -1419,27 +1403,31 @@ static zend_result php_session_send_cookie(void) } } - if (PS(cookie_path)[0]) { + if (ZSTR_LEN(PS(cookie_path))) { smart_str_appends(&ncookie, COOKIE_PATH); - smart_str_appends(&ncookie, PS(cookie_path)); + smart_str_append(&ncookie, PS(cookie_path)); } - if (PS(cookie_domain)[0]) { + if (ZSTR_LEN(PS(cookie_domain))) { smart_str_appends(&ncookie, COOKIE_DOMAIN); - smart_str_appends(&ncookie, PS(cookie_domain)); + smart_str_append(&ncookie, PS(cookie_domain)); } if (PS(cookie_secure)) { smart_str_appends(&ncookie, COOKIE_SECURE); } + if (PS(cookie_partitioned)) { + smart_str_appends(&ncookie, COOKIE_PARTITIONED); + } + if (PS(cookie_httponly)) { smart_str_appends(&ncookie, COOKIE_HTTPONLY); } - if (PS(cookie_samesite)[0]) { + if (ZSTR_LEN(PS(cookie_samesite))) { smart_str_appends(&ncookie, COOKIE_SAMESITE); - smart_str_appends(&ncookie, PS(cookie_samesite)); + smart_str_append(&ncookie, PS(cookie_samesite)); } smart_str_0(&ncookie); @@ -1455,37 +1443,132 @@ static zend_result php_session_send_cookie(void) PHPAPI const ps_module *_php_find_ps_module(const char *name) { - const ps_module *ret = NULL; - const ps_module **mod; - int i; + const ps_module *found_module = NULL; + const ps_module **current_module; + int module_index; - for (i = 0, mod = ps_modules; i < MAX_MODULES; i++, mod++) { - if (*mod && !strcasecmp(name, (*mod)->s_name)) { - ret = *mod; + for (module_index = 0, current_module = ps_modules; module_index < MAX_MODULES; module_index++, current_module++) { + if (*current_module && !strcasecmp(name, (*current_module)->s_name)) { + found_module = *current_module; break; } } - return ret; + return found_module; } PHPAPI const ps_serializer *_php_find_ps_serializer(const char *name) { - const ps_serializer *ret = NULL; - const ps_serializer *mod; + const ps_serializer *found_serializer = NULL; + const ps_serializer *current_serializer; - for (mod = ps_serializers; mod->name; mod++) { - if (!strcasecmp(name, mod->name)) { - ret = mod; + for (current_serializer = ps_serializers; current_serializer->name; current_serializer++) { + if (!strcasecmp(name, current_serializer->name)) { + found_serializer = current_serializer; break; } } - return ret; + return found_serializer; } -static void ppid2sid(zval *ppid) { - ZVAL_DEREF(ppid); - if (Z_TYPE_P(ppid) == IS_STRING) { - PS(id) = zend_string_init(Z_STRVAL_P(ppid), Z_STRLEN_P(ppid), 0); +static bool should_invalidate_session_for_external_referer(void) +{ + zval *referer_data; + + /* No external referer check configured */ + if (!PS(id) || PS(extern_referer_chk)[0] == '\0') { + return false; + } + + /* No SERVER globals available */ + if (Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER])) { + return false; + } + + /* Get HTTP_REFERER header */ + referer_data = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZEND_STRL("HTTP_REFERER")); + if (!referer_data || Z_TYPE_P(referer_data) != IS_STRING || Z_STRLEN_P(referer_data) == 0) { + return false; + } + + /* Check if referer contains expected string */ + return strstr(Z_STRVAL_P(referer_data), PS(extern_referer_chk)) == NULL; +} + +static void try_find_session_id_in_global(const char *global_name, size_t global_name_len) +{ + zval *global_data, *potential_session_id; + + if (PS(id)) { + return; + } + + global_data = zend_hash_str_find(&EG(symbol_table), global_name, global_name_len); + if (!global_data) { + return; + } + + ZVAL_DEREF(global_data); + if (Z_TYPE_P(global_data) != IS_ARRAY) { + return; + } + + potential_session_id = zend_hash_find(Z_ARRVAL_P(global_data), PS(session_name)); + if (potential_session_id) { + proposed_session_id_to_session_id(potential_session_id); + } +} + +static bool php_can_change_session_setting(const char *setting_name, bool check_cookies) +{ + if (PS(session_status) == php_session_active) { + char error_msg[256]; + snprintf(error_msg, sizeof(error_msg), "Session %s cannot be changed when a session is active", setting_name); + php_session_session_already_started_error(E_WARNING, error_msg); + + return false; + } + + if (SG(headers_sent) && (!check_cookies || PS(use_cookies))) { + char error_msg[256]; + snprintf(error_msg, sizeof(error_msg), "Session %s cannot be changed after headers have already been sent", setting_name); + php_session_headers_already_sent_error(E_WARNING, error_msg); + + return false; + } + + return true; +} + +static void try_find_session_id_in_cookies(void) +{ + zval *cookie_data, *potential_session_id; + + if (!PS(use_cookies) || PS(id)) { + return; + } + + cookie_data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_COOKIE")); + if (!cookie_data) { + return; + } + + ZVAL_DEREF(cookie_data); + if (Z_TYPE_P(cookie_data) != IS_ARRAY) { + return; + } + + potential_session_id = zend_hash_find(Z_ARRVAL_P(cookie_data), PS(session_name)); + if (potential_session_id) { + proposed_session_id_to_session_id(potential_session_id); + PS(send_cookie) = 0; + PS(define_sid) = 0; + } +} + +static void proposed_session_id_to_session_id(zval *proposed_session_id) { + ZVAL_DEREF(proposed_session_id); + if (Z_TYPE_P(proposed_session_id) == IS_STRING) { + PS(id) = zend_string_copy(Z_STR_P(proposed_session_id)); PS(send_cookie) = 0; } else { PS(id) = NULL; @@ -1497,7 +1580,7 @@ static void ppid2sid(zval *ppid) { PHPAPI zend_result php_session_reset_id(void) { int module_number = PS(module_number); - zval *sid, *data, *ppid; + zval *sid, *data, *potential_session_id; bool apply_trans_sid; if (!PS(id)) { @@ -1515,21 +1598,23 @@ PHPAPI zend_result php_session_reset_id(void) /* If the SID constant exists, destroy it. */ /* We must not delete any items in EG(zend_constants) */ - /* zend_hash_str_del(EG(zend_constants), "sid", sizeof("sid") - 1); */ - sid = zend_get_constant_str("SID", sizeof("SID") - 1); + /* zend_hash_str_del(EG(zend_constants), ZEND_STRL("sid")); */ + sid = zend_get_constant_str(ZEND_STRL("SID")); + + zend_constant *new_sid_constant = NULL; if (PS(define_sid)) { smart_str var = {0}; - smart_str_appends(&var, PS(session_name)); + smart_str_append(&var, PS(session_name)); smart_str_appendc(&var, '='); - smart_str_appends(&var, ZSTR_VAL(PS(id))); + smart_str_append(&var, PS(id)); smart_str_0(&var); if (sid) { zval_ptr_dtor(sid); ZVAL_STR(sid, smart_str_extract(&var)); } else { - REGISTER_STRINGL_CONSTANT("SID", ZSTR_VAL(var.s), ZSTR_LEN(var.s), CONST_DEPRECATED); + new_sid_constant = REGISTER_STRINGL_CONSTANT("SID", ZSTR_VAL(var.s), ZSTR_LEN(var.s), CONST_DEPRECATED); smart_str_free(&var); } } else { @@ -1537,30 +1622,35 @@ PHPAPI zend_result php_session_reset_id(void) zval_ptr_dtor(sid); ZVAL_EMPTY_STRING(sid); } else { - REGISTER_STRINGL_CONSTANT("SID", "", 0, CONST_DEPRECATED); + new_sid_constant = REGISTER_STRINGL_CONSTANT("SID", "", 0, CONST_DEPRECATED); } } + if (new_sid_constant != NULL) { + zend_string *deprecation_reason = zend_string_init("as GET/POST sessions were deprecated", strlen("as GET/POST sessions were deprecated"), 0); + zend_attribute *deprecation_attrib = zend_add_attribute(&new_sid_constant->attributes, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2, 0, 0, 0); + ZVAL_STR(&deprecation_attrib->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + deprecation_attrib->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR(&deprecation_attrib->args[1].value, deprecation_reason); + deprecation_attrib->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + } /* Apply trans sid if sid cookie is not set */ apply_trans_sid = 0; if (APPLY_TRANS_SID) { apply_trans_sid = 1; if (PS(use_cookies) && - (data = zend_hash_str_find(&EG(symbol_table), "_COOKIE", sizeof("_COOKIE") - 1))) { + (data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_COOKIE")))) { ZVAL_DEREF(data); if (Z_TYPE_P(data) == IS_ARRAY && - (ppid = zend_hash_str_find(Z_ARRVAL_P(data), PS(session_name), strlen(PS(session_name))))) { - ZVAL_DEREF(ppid); + (potential_session_id = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) { + ZVAL_DEREF(potential_session_id); apply_trans_sid = 0; } } } if (apply_trans_sid) { - zend_string *sname; - sname = zend_string_init(PS(session_name), strlen(PS(session_name)), 0); - php_url_scanner_reset_session_var(sname, 1); /* This may fail when session name has changed */ - zend_string_release_ex(sname, 0); - php_url_scanner_add_session_var(PS(session_name), strlen(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), 1); + php_url_scanner_reset_session_var(PS(session_name), true); /* This may fail when session name has changed */ + php_url_scanner_add_session_var(ZSTR_VAL(PS(session_name)), ZSTR_LEN(PS(session_name)), ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)), true); } return SUCCESS; } @@ -1568,10 +1658,7 @@ PHPAPI zend_result php_session_reset_id(void) PHPAPI zend_result php_session_start(void) { - zval *ppid; - zval *data; char *value; - size_t lensess; switch (PS(session_status)) { case php_session_active: @@ -1580,7 +1667,7 @@ PHPAPI zend_result php_session_start(void) break; case php_session_disabled: - value = zend_ini_string("session.save_handler", sizeof("session.save_handler") - 1, 0); + value = zend_ini_string(ZEND_STRL("session.save_handler"), false); if (!PS(mod) && value) { PS(mod) = _php_find_ps_module(value); if (!PS(mod)) { @@ -1588,7 +1675,7 @@ PHPAPI zend_result php_session_start(void) return FAILURE; } } - value = zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler") - 1, 0); + value = zend_ini_string(ZEND_STRL("session.serialize_handler"), false); if (!PS(serializer) && value) { PS(serializer) = _php_find_ps_serializer(value); if (!PS(serializer)) { @@ -1606,8 +1693,6 @@ PHPAPI zend_result php_session_start(void) PS(send_cookie) = PS(use_cookies) || PS(use_only_cookies); } - lensess = strlen(PS(session_name)); - /* * Cookies are preferred, because initially cookie and get * variables will be available. @@ -1617,37 +1702,13 @@ PHPAPI zend_result php_session_start(void) */ if (!PS(id)) { - if (PS(use_cookies) && (data = zend_hash_str_find(&EG(symbol_table), "_COOKIE", sizeof("_COOKIE") - 1))) { - ZVAL_DEREF(data); - if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_str_find(Z_ARRVAL_P(data), PS(session_name), lensess))) { - ppid2sid(ppid); - PS(send_cookie) = 0; - PS(define_sid) = 0; - } - } - /* Initialize session ID from non cookie values */ + try_find_session_id_in_cookies(); + if (!PS(use_only_cookies)) { - if (!PS(id) && (data = zend_hash_str_find(&EG(symbol_table), "_GET", sizeof("_GET") - 1))) { - ZVAL_DEREF(data); - if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_str_find(Z_ARRVAL_P(data), PS(session_name), lensess))) { - ppid2sid(ppid); - } - } - if (!PS(id) && (data = zend_hash_str_find(&EG(symbol_table), "_POST", sizeof("_POST") - 1))) { - ZVAL_DEREF(data); - if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_str_find(Z_ARRVAL_P(data), PS(session_name), lensess))) { - ppid2sid(ppid); - } - } - /* Check whether the current request was referred to by - * an external site which invalidates the previously found id. */ - if (PS(id) && PS(extern_referer_chk)[0] != '\0' && - !Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER]) && - (data = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_REFERER", sizeof("HTTP_REFERER") - 1)) && - Z_TYPE_P(data) == IS_STRING && - Z_STRLEN_P(data) != 0 && - strstr(Z_STRVAL_P(data), PS(extern_referer_chk)) == NULL - ) { + try_find_session_id_in_global(ZEND_STRL("_GET")); + try_find_session_id_in_global(ZEND_STRL("_POST")); + + if (should_invalidate_session_for_external_referer()) { zend_string_release_ex(PS(id), 0); PS(id) = NULL; } @@ -1717,7 +1778,7 @@ static zend_result php_session_reset(void) PHPAPI void session_adapt_url(const char *url, size_t url_len, char **new_url, size_t *new_len) { if (APPLY_TRANS_SID && (PS(session_status) == php_session_active)) { - *new_url = php_url_scanner_adapt_single_url(url, url_len, PS(session_name), ZSTR_VAL(PS(id)), new_len, 1); + *new_url = php_url_scanner_adapt_single_url(url, url_len, ZSTR_VAL(PS(session_name)), ZSTR_VAL(PS(id)), new_len, true); } } @@ -1732,6 +1793,7 @@ PHP_FUNCTION(session_set_cookie_params) zend_string *lifetime = NULL, *path = NULL, *domain = NULL, *samesite = NULL; bool secure = 0, secure_null = 1; bool httponly = 0, httponly_null = 1; + bool partitioned = false, partitioned_null = true; zend_string *ini_name; zend_result result; int found = 0; @@ -1799,6 +1861,10 @@ PHP_FUNCTION(session_set_cookie_params) secure = zval_is_true(value); secure_null = 0; found++; + } else if (zend_string_equals_literal_ci(key, "partitioned")) { + partitioned = zval_is_true(value); + partitioned_null = 0; + found++; } else if (zend_string_equals_literal_ci(key, "httponly")) { httponly = zval_is_true(value); httponly_null = 0; @@ -1863,6 +1929,15 @@ PHP_FUNCTION(session_set_cookie_params) goto cleanup; } } + if (!partitioned_null) { + ini_name = ZSTR_INIT_LITERAL("session.cookie_partitioned", 0); + result = zend_alter_ini_entry_chars(ini_name, partitioned ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); + zend_string_release_ex(ini_name, 0); + if (result == FAILURE) { + RETVAL_FALSE; + goto cleanup; + } + } if (!httponly_null) { ini_name = ZSTR_INIT_LITERAL("session.cookie_httponly", 0); result = zend_alter_ini_entry_chars(ini_name, httponly ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); @@ -1902,37 +1977,31 @@ PHP_FUNCTION(session_get_cookie_params) array_init(return_value); add_assoc_long(return_value, "lifetime", PS(cookie_lifetime)); - add_assoc_string(return_value, "path", PS(cookie_path)); - add_assoc_string(return_value, "domain", PS(cookie_domain)); + add_assoc_str(return_value, "path", zend_string_dup(PS(cookie_path), false)); + add_assoc_str(return_value, "domain", zend_string_dup(PS(cookie_domain), false)); add_assoc_bool(return_value, "secure", PS(cookie_secure)); + add_assoc_bool(return_value, "partitioned", PS(cookie_partitioned)); add_assoc_bool(return_value, "httponly", PS(cookie_httponly)); - add_assoc_string(return_value, "samesite", PS(cookie_samesite)); + add_assoc_str(return_value, "samesite", zend_string_dup(PS(cookie_samesite), false)); } /* Return the current session name. If new name is given, the session name is replaced with new name */ PHP_FUNCTION(session_name) { zend_string *name = NULL; - zend_string *ini_name; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|P!", &name) == FAILURE) { RETURN_THROWS(); } - if (name && PS(session_status) == php_session_active) { - php_session_session_already_started_error(E_WARNING, "Session name cannot be changed when a session is active"); + if (name && !php_can_change_session_setting("name", false)) { RETURN_FALSE; } - if (name && SG(headers_sent)) { - php_session_headers_already_sent_error(E_WARNING, "Session name cannot be changed after headers have already been sent"); - RETURN_FALSE; - } - - RETVAL_STRING(PS(session_name)); + RETVAL_STRINGL(ZSTR_VAL(PS(session_name)), ZSTR_LEN(PS(session_name))); if (name) { - ini_name = ZSTR_INIT_LITERAL("session.name", 0); + zend_string *ini_name = ZSTR_INIT_LITERAL("session.name", 0); zend_alter_ini_entry(ini_name, name, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); zend_string_release_ex(ini_name, 0); } @@ -1948,13 +2017,7 @@ PHP_FUNCTION(session_module_name) RETURN_THROWS(); } - if (name && PS(session_status) == php_session_active) { - php_session_session_already_started_error(E_WARNING, "Session save handler module cannot be changed when a session is active"); - RETURN_FALSE; - } - - if (name && SG(headers_sent)) { - php_session_headers_already_sent_error(E_WARNING, "Session save handler module cannot be changed after headers have already been sent"); + if (name && !php_can_change_session_setting("save handler module", false)) { RETURN_FALSE; } @@ -2218,28 +2281,21 @@ PHP_FUNCTION(session_set_save_handler) PHP_FUNCTION(session_save_path) { zend_string *name = NULL; - zend_string *ini_name; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|P!", &name) == FAILURE) { RETURN_THROWS(); } - if (name && PS(session_status) == php_session_active) { - php_session_session_already_started_error(E_WARNING, "Session save path cannot be changed when a session is active"); + if (name && !php_can_change_session_setting("save path", false)) { RETURN_FALSE; } - if (name && SG(headers_sent)) { - php_session_headers_already_sent_error(E_WARNING, "Session save path cannot be changed after headers have already been sent"); - RETURN_FALSE; - } - - RETVAL_STRING(PS(save_path)); + RETVAL_STRINGL(ZSTR_VAL(PS(save_path)), ZSTR_LEN(PS(save_path))); if (name) { - ini_name = ZSTR_INIT_LITERAL("session.save_path", 0); + zend_string *ini_name = ZSTR_INIT_LITERAL("session.save_path", false); zend_alter_ini_entry(ini_name, name, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); - zend_string_release_ex(ini_name, 0); + zend_string_release_ex(ini_name, false); } } @@ -2252,13 +2308,7 @@ PHP_FUNCTION(session_id) RETURN_THROWS(); } - if (name && PS(session_status) == php_session_active) { - php_session_session_already_started_error(E_WARNING, "Session ID cannot be changed when a session is active"); - RETURN_FALSE; - } - - if (name && PS(use_cookies) && SG(headers_sent)) { - php_session_headers_already_sent_error(E_WARNING, "Session ID cannot be changed after headers have already been sent"); + if (name && !php_can_change_session_setting("ID", true)) { RETURN_FALSE; } @@ -2309,7 +2359,7 @@ PHP_FUNCTION(session_regenerate_id) PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; if (!EG(exception)) { - php_error_docref(NULL, E_WARNING, "Session object destruction failed. ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_WARNING, "Session object destruction failed. ID: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } RETURN_FALSE; } @@ -2325,7 +2375,7 @@ PHP_FUNCTION(session_regenerate_id) if (ret == FAILURE) { PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; - php_error_docref(NULL, E_WARNING, "Session write failed. ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_WARNING, "Session write failed. ID: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); RETURN_FALSE; } } @@ -2339,10 +2389,10 @@ PHP_FUNCTION(session_regenerate_id) zend_string_release_ex(PS(id), 0); PS(id) = NULL; - if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE) { + if (PS(mod)->s_open(&PS(mod_data), ZSTR_VAL(PS(save_path)), ZSTR_VAL(PS(session_name))) == FAILURE) { PS(session_status) = php_session_none; if (!EG(exception)) { - zend_throw_error(NULL, "Failed to open session: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + zend_throw_error(NULL, "Failed to open session: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } RETURN_THROWS(); } @@ -2351,7 +2401,7 @@ PHP_FUNCTION(session_regenerate_id) if (!PS(id)) { PS(session_status) = php_session_none; if (!EG(exception)) { - zend_throw_error(NULL, "Failed to create new session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + zend_throw_error(NULL, "Failed to create new session ID: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } RETURN_THROWS(); } @@ -2366,7 +2416,7 @@ PHP_FUNCTION(session_regenerate_id) PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; if (!EG(exception)) { - zend_throw_error(NULL, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + zend_throw_error(NULL, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } RETURN_THROWS(); } @@ -2379,7 +2429,7 @@ PHP_FUNCTION(session_regenerate_id) PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; if (!EG(exception)) { - zend_throw_error(NULL, "Failed to create(read) session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + zend_throw_error(NULL, "Failed to create(read) session ID: %s (path: %s)", PS(mod)->s_name, ZSTR_VAL(PS(save_path))); } RETURN_THROWS(); } @@ -2472,7 +2522,7 @@ PHP_FUNCTION(session_cache_limiter) RETURN_FALSE; } - RETVAL_STRING(PS(cache_limiter)); + RETVAL_STRINGL(ZSTR_VAL(PS(cache_limiter)), ZSTR_LEN(PS(cache_limiter))); if (limiter) { ini_name = ZSTR_INIT_LITERAL("session.cache_limiter", 0); @@ -2604,7 +2654,7 @@ PHP_FUNCTION(session_start) if (Z_TYPE_P(value) != IS_STRING) { tmp = zval_get_long(value); } else { - if (is_numeric_string(Z_STRVAL_P(value), Z_STRLEN_P(value), &tmp, NULL, false) != IS_LONG) { + if (is_numeric_str_function(Z_STR_P(value), &tmp, NULL) != IS_LONG) { zend_type_error("%s(): Option \"%s\" value must be of type compatible with int, \"%s\" given", get_active_function_name(), ZSTR_VAL(str_idx), Z_STRVAL_P(value) ); @@ -2795,7 +2845,7 @@ static zend_result php_rinit_session(bool auto_start) { char *value; - value = zend_ini_string("session.save_handler", sizeof("session.save_handler") - 1, 0); + value = zend_ini_string(ZEND_STRL("session.save_handler"), false); if (value) { PS(mod) = _php_find_ps_module(value); } @@ -2804,7 +2854,7 @@ static zend_result php_rinit_session(bool auto_start) if (PS(serializer) == NULL) { char *value; - value = zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler") - 1, 0); + value = zend_ini_string(ZEND_STRL("session.serialize_handler"), false); if (value) { PS(serializer) = _php_find_ps_serializer(value); } @@ -2908,7 +2958,7 @@ static PHP_GINIT_FUNCTION(ps) static PHP_MINIT_FUNCTION(session) { - zend_register_auto_global(zend_string_init_interned("_SESSION", sizeof("_SESSION") - 1, 1), 0, NULL); + zend_register_auto_global(zend_string_init_interned(ZEND_STRL("_SESSION"), true), false, NULL); my_module_number = module_number; PS(module_number) = module_number; @@ -2959,24 +3009,24 @@ static PHP_MSHUTDOWN_FUNCTION(session) static PHP_MINFO_FUNCTION(session) { - const ps_module **mod; - ps_serializer *ser; + const ps_module **current_save_handler; + ps_serializer *current_serializer; smart_str save_handlers = {0}; smart_str ser_handlers = {0}; - int i; + int handler_index; - /* Get save handlers */ - for (i = 0, mod = ps_modules; i < MAX_MODULES; i++, mod++) { - if (*mod && (*mod)->s_name) { - smart_str_appends(&save_handlers, (*mod)->s_name); + /* Collect names of all available save handlers */ + for (handler_index = 0, current_save_handler = ps_modules; handler_index < MAX_MODULES; handler_index++, current_save_handler++) { + if (*current_save_handler && (*current_save_handler)->s_name) { + smart_str_appends(&save_handlers, (*current_save_handler)->s_name); smart_str_appendc(&save_handlers, ' '); } } - /* Get serializer handlers */ - for (i = 0, ser = ps_serializers; i < MAX_SERIALIZERS; i++, ser++) { - if (ser->name) { - smart_str_appends(&ser_handlers, ser->name); + /* Collect names of all available serializers */ + for (handler_index = 0, current_serializer = ps_serializers; handler_index < MAX_SERIALIZERS; handler_index++, current_serializer++) { + if (current_serializer->name) { + smart_str_appends(&ser_handlers, current_serializer->name); smart_str_appendc(&ser_handlers, ' '); } } @@ -3016,16 +3066,16 @@ static const zend_module_dep session_deps[] = { static bool early_find_sid_in(zval *dest, int where, php_session_rfc1867_progress *progress) { - zval *ppid; + zval *potential_session_id; if (Z_ISUNDEF(PG(http_globals)[where])) { return 0; } - if ((ppid = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[where]), PS(session_name), progress->sname_len)) - && Z_TYPE_P(ppid) == IS_STRING) { + if ((potential_session_id = zend_hash_find(Z_ARRVAL(PG(http_globals)[where]), PS(session_name))) + && Z_TYPE_P(potential_session_id) == IS_STRING) { zval_ptr_dtor(dest); - ZVAL_COPY_DEREF(dest, ppid); + ZVAL_COPY_DEREF(dest, potential_session_id); return 1; } @@ -3059,13 +3109,13 @@ static bool php_check_cancel_upload(php_session_rfc1867_progress *progress) if (Z_TYPE_P(progress_ary) != IS_ARRAY) { return 0; } - if ((cancel_upload = zend_hash_str_find(Z_ARRVAL_P(progress_ary), "cancel_upload", sizeof("cancel_upload") - 1)) == NULL) { + if ((cancel_upload = zend_hash_str_find(Z_ARRVAL_P(progress_ary), ZEND_STRL("cancel_upload"))) == NULL) { return 0; } return Z_TYPE_P(cancel_upload) == IS_TRUE; } -static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, int force_update) +static void php_session_rfc1867_update(php_session_rfc1867_progress *progress, bool force_update) { if (!force_update) { if (Z_LVAL_P(progress->post_bytes_processed) < progress->next_update) { @@ -3130,7 +3180,6 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ multipart_event_start *data = (multipart_event_start *) event_data; progress = ecalloc(1, sizeof(php_session_rfc1867_progress)); progress->content_length = data->content_length; - progress->sname_len = strlen(PS(session_name)); PS(rfc1867_progress) = progress; } break; @@ -3152,12 +3201,12 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ if (data->name && data->value && value_len) { size_t name_len = strlen(data->name); - if (name_len == progress->sname_len && memcmp(data->name, PS(session_name), name_len) == 0) { + if (zend_string_equals_cstr(PS(session_name), data->name, name_len)) { zval_ptr_dtor(&progress->sid); ZVAL_STRINGL(&progress->sid, (*data->value), value_len); - } else if (name_len == strlen(PS(rfc1867_name)) && memcmp(data->name, PS(rfc1867_name), name_len + 1) == 0) { + } else if (zend_string_equals_cstr(PS(rfc1867_name), data->name, name_len)) { smart_str_free(&progress->key); - smart_str_appends(&progress->key, PS(rfc1867_prefix)); + smart_str_append(&progress->key, PS(rfc1867_prefix)); smart_str_appendl(&progress->key, *data->value, value_len); smart_str_0(&progress->key); @@ -3190,16 +3239,16 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ array_init(&progress->data); array_init(&progress->files); - add_assoc_long_ex(&progress->data, "start_time", sizeof("start_time") - 1, (zend_long)sapi_get_request_time()); - add_assoc_long_ex(&progress->data, "content_length", sizeof("content_length") - 1, progress->content_length); - add_assoc_long_ex(&progress->data, "bytes_processed", sizeof("bytes_processed") - 1, data->post_bytes_processed); - add_assoc_bool_ex(&progress->data, "done", sizeof("done") - 1, 0); - add_assoc_zval_ex(&progress->data, "files", sizeof("files") - 1, &progress->files); + add_assoc_long_ex(&progress->data, ZEND_STRL("start_time"), (zend_long)sapi_get_request_time()); + add_assoc_long_ex(&progress->data, ZEND_STRL("content_length"), progress->content_length); + add_assoc_long_ex(&progress->data, ZEND_STRL("bytes_processed"), data->post_bytes_processed); + add_assoc_bool_ex(&progress->data, ZEND_STRL("done"), false); + add_assoc_zval_ex(&progress->data, ZEND_STRL("files"), &progress->files); - progress->post_bytes_processed = zend_hash_str_find(Z_ARRVAL(progress->data), "bytes_processed", sizeof("bytes_processed") - 1); + progress->post_bytes_processed = zend_hash_str_find(Z_ARRVAL(progress->data), ZEND_STRL("bytes_processed")); php_rinit_session(0); - PS(id) = zend_string_init(Z_STRVAL(progress->sid), Z_STRLEN(progress->sid), 0); + PS(id) = zend_string_copy(Z_STR(progress->sid)); if (progress->apply_trans_sid) { /* Enable trans sid by modifying flags */ PS(use_trans_sid) = 1; @@ -3211,18 +3260,18 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ array_init(&progress->current_file); /* Each uploaded file has its own array. Trying to make it close to $_FILES entries. */ - add_assoc_string_ex(&progress->current_file, "field_name", sizeof("field_name") - 1, data->name); - add_assoc_string_ex(&progress->current_file, "name", sizeof("name") - 1, *data->filename); - add_assoc_null_ex(&progress->current_file, "tmp_name", sizeof("tmp_name") - 1); - add_assoc_long_ex(&progress->current_file, "error", sizeof("error") - 1, 0); + add_assoc_string_ex(&progress->current_file, ZEND_STRL("field_name"), data->name); + add_assoc_string_ex(&progress->current_file, ZEND_STRL("name"), *data->filename); + add_assoc_null_ex(&progress->current_file, ZEND_STRL("tmp_name")); + add_assoc_long_ex(&progress->current_file, ZEND_STRL("error"), 0); - add_assoc_bool_ex(&progress->current_file, "done", sizeof("done") - 1, 0); - add_assoc_long_ex(&progress->current_file, "start_time", sizeof("start_time") - 1, (zend_long)time(NULL)); - add_assoc_long_ex(&progress->current_file, "bytes_processed", sizeof("bytes_processed") - 1, 0); + add_assoc_bool_ex(&progress->current_file, ZEND_STRL("done"), 0); + add_assoc_long_ex(&progress->current_file, ZEND_STRL("start_time"), (zend_long)time(NULL)); + add_assoc_long_ex(&progress->current_file, ZEND_STRL("bytes_processed"), 0); add_next_index_zval(&progress->files, &progress->current_file); - progress->current_file_bytes_processed = zend_hash_str_find(Z_ARRVAL(progress->current_file), "bytes_processed", sizeof("bytes_processed") - 1); + progress->current_file_bytes_processed = zend_hash_str_find(Z_ARRVAL(progress->current_file), ZEND_STRL("bytes_processed")); Z_LVAL_P(progress->current_file_bytes_processed) = data->post_bytes_processed; php_session_rfc1867_update(progress, 0); @@ -3249,11 +3298,11 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ } if (data->temp_filename) { - add_assoc_string_ex(&progress->current_file, "tmp_name", sizeof("tmp_name") - 1, data->temp_filename); + add_assoc_string_ex(&progress->current_file, ZEND_STRL("tmp_name"), data->temp_filename); } - add_assoc_long_ex(&progress->current_file, "error", sizeof("error") - 1, data->cancel_upload); - add_assoc_bool_ex(&progress->current_file, "done", sizeof("done") - 1, 1); + add_assoc_long_ex(&progress->current_file, ZEND_STRL("error"), data->cancel_upload); + add_assoc_bool_ex(&progress->current_file, ZEND_STRL("done"), 1); Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; @@ -3269,7 +3318,7 @@ static zend_result php_session_rfc1867_callback(unsigned int event, void *event_ } else { if (!Z_ISUNDEF(progress->data)) { SEPARATE_ARRAY(&progress->data); - add_assoc_bool_ex(&progress->data, "done", sizeof("done") - 1, 1); + add_assoc_bool_ex(&progress->data, ZEND_STRL("done"), 1); Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; php_session_rfc1867_update(progress, 1); } diff --git a/ext/session/tests/015.phpt b/ext/session/tests/015.phpt index 3154022fae861..1a9285c339332 100644 --- a/ext/session/tests/015.phpt +++ b/ext/session/tests/015.phpt @@ -31,5 +31,5 @@ Deprecated: PHP Startup: Disabling session.use_only_cookies INI setting is depre Deprecated: PHP Startup: Enabling session.use_trans_sid INI setting is deprecated in Unknown on line 0 -Deprecated: Constant SID is deprecated in %s on line 6 +Deprecated: Constant SID is deprecated since 8.4, as GET/POST sessions were deprecated in %s on line %d diff --git a/ext/session/tests/bug53141.phpt b/ext/session/tests/bug53141.phpt index 849a358760400..81ce8e3bd0a89 100644 --- a/ext/session/tests/bug53141.phpt +++ b/ext/session/tests/bug53141.phpt @@ -13,10 +13,10 @@ spl_autoload_register(function ($class) { class Foo { - function __sleep() + function __serialize() { new Bar; - return array(); + return []; } } diff --git a/ext/session/tests/bug72940.phpt b/ext/session/tests/bug72940.phpt index 9a927a5419e4a..4977b05a55233 100644 --- a/ext/session/tests/bug72940.phpt +++ b/ext/session/tests/bug72940.phpt @@ -34,12 +34,12 @@ session_destroy(); --EXPECTF-- Deprecated: ini_set(): Disabling session.use_only_cookies INI setting is deprecated in %s on line 6 -Deprecated: Constant SID is deprecated in %s on line 8 +Deprecated: Constant SID is deprecated since 8.4, as GET/POST sessions were deprecated in %s on line %d string(12) "bug72940test" string(0) "" Deprecated: ini_set(): Disabling session.use_only_cookies INI setting is deprecated in %s on line 13 -Deprecated: Constant SID is deprecated in %s on line 15 +Deprecated: Constant SID is deprecated since 8.4, as GET/POST sessions were deprecated in %s on line %d string(11) "bug72940get" string(21) "PHPSESSID=bug72940get" diff --git a/ext/session/tests/deprecations.phpt b/ext/session/tests/deprecations.phpt index 4a2337fb99dad..0db8ce49b7d0c 100644 --- a/ext/session/tests/deprecations.phpt +++ b/ext/session/tests/deprecations.phpt @@ -60,5 +60,5 @@ Deprecated: session_start(): Disabling session.use_only_cookies INI setting is d Deprecated: session_start(): Enabling session.use_trans_sid INI setting is deprecated in %s on line 32 -Deprecated: Constant SID is deprecated in %s on line 34 +Deprecated: Constant SID is deprecated since 8.4, as GET/POST sessions were deprecated in %s on line %d PHPSESSID=%s diff --git a/ext/session/tests/session_get_cookie_params_basic.phpt b/ext/session/tests/session_get_cookie_params_basic.phpt index 65b020d30b9ec..1c7cdf189fc9d 100644 --- a/ext/session/tests/session_get_cookie_params_basic.phpt +++ b/ext/session/tests/session_get_cookie_params_basic.phpt @@ -9,6 +9,7 @@ session.cookie_lifetime=0 session.cookie_path="/" session.cookie_domain="" session.cookie_secure=0 +session.cookie_partitioned=0 session.cookie_httponly=0 session.cookie_samesite="" --FILE-- @@ -31,13 +32,17 @@ var_dump(session_set_cookie_params([ "httponly" => FALSE, "samesite" => "please"])); var_dump(session_get_cookie_params()); +var_dump(session_set_cookie_params([ + "secure" => TRUE, + "partitioned" => TRUE])); +var_dump(session_get_cookie_params()); echo "Done"; ob_end_flush(); ?> --EXPECTF-- *** Testing session_get_cookie_params() : basic functionality *** -array(6) { +array(7) { ["lifetime"]=> int(0) ["path"]=> @@ -46,13 +51,15 @@ array(6) { string(0) "" ["secure"]=> bool(false) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(false) ["samesite"]=> string(0) "" } bool(true) -array(6) { +array(7) { ["lifetime"]=> int(3600) ["path"]=> @@ -61,13 +68,15 @@ array(6) { string(4) "blah" ["secure"]=> bool(false) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(false) ["samesite"]=> string(0) "" } bool(true) -array(6) { +array(7) { ["lifetime"]=> int(%d) ["path"]=> @@ -76,13 +85,15 @@ array(6) { string(3) "foo" ["secure"]=> bool(true) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(true) ["samesite"]=> string(0) "" } bool(true) -array(6) { +array(7) { ["lifetime"]=> int(123) ["path"]=> @@ -91,6 +102,25 @@ array(6) { string(3) "baz" ["secure"]=> bool(false) + ["partitioned"]=> + bool(false) + ["httponly"]=> + bool(false) + ["samesite"]=> + string(6) "please" +} +bool(true) +array(7) { + ["lifetime"]=> + int(123) + ["path"]=> + string(4) "/bar" + ["domain"]=> + string(3) "baz" + ["secure"]=> + bool(true) + ["partitioned"]=> + bool(true) ["httponly"]=> bool(false) ["samesite"]=> diff --git a/ext/session/tests/session_get_cookie_params_variation1.phpt b/ext/session/tests/session_get_cookie_params_variation1.phpt index 4feb0d3ec81d1..7ce112c9b94dd 100644 --- a/ext/session/tests/session_get_cookie_params_variation1.phpt +++ b/ext/session/tests/session_get_cookie_params_variation1.phpt @@ -9,6 +9,7 @@ session.cookie_lifetime=0 session.cookie_path="/" session.cookie_domain="" session.cookie_secure=0 +session.cookie_partitioned=0 session.cookie_httponly=0 session.cookie_samesite="" --FILE-- @@ -31,13 +32,15 @@ ini_set("session.cookie_httponly", TRUE); var_dump(session_get_cookie_params()); ini_set("session.cookie_samesite", "foo"); var_dump(session_get_cookie_params()); +ini_set("session.cookie_partitioned", TRUE); +var_dump(session_get_cookie_params()); echo "Done"; ob_end_flush(); ?> --EXPECT-- *** Testing session_get_cookie_params() : variation *** -array(6) { +array(7) { ["lifetime"]=> int(0) ["path"]=> @@ -46,12 +49,14 @@ array(6) { string(0) "" ["secure"]=> bool(false) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(false) ["samesite"]=> string(0) "" } -array(6) { +array(7) { ["lifetime"]=> int(3600) ["path"]=> @@ -60,12 +65,14 @@ array(6) { string(0) "" ["secure"]=> bool(false) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(false) ["samesite"]=> string(0) "" } -array(6) { +array(7) { ["lifetime"]=> int(3600) ["path"]=> @@ -74,12 +81,14 @@ array(6) { string(0) "" ["secure"]=> bool(false) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(false) ["samesite"]=> string(0) "" } -array(6) { +array(7) { ["lifetime"]=> int(3600) ["path"]=> @@ -88,12 +97,14 @@ array(6) { string(3) "foo" ["secure"]=> bool(false) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(false) ["samesite"]=> string(0) "" } -array(6) { +array(7) { ["lifetime"]=> int(3600) ["path"]=> @@ -102,12 +113,14 @@ array(6) { string(3) "foo" ["secure"]=> bool(true) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(false) ["samesite"]=> string(0) "" } -array(6) { +array(7) { ["lifetime"]=> int(3600) ["path"]=> @@ -116,12 +129,30 @@ array(6) { string(3) "foo" ["secure"]=> bool(true) + ["partitioned"]=> + bool(false) ["httponly"]=> bool(true) ["samesite"]=> string(0) "" } -array(6) { +array(7) { + ["lifetime"]=> + int(3600) + ["path"]=> + string(5) "/path" + ["domain"]=> + string(3) "foo" + ["secure"]=> + bool(true) + ["partitioned"]=> + bool(false) + ["httponly"]=> + bool(true) + ["samesite"]=> + string(3) "foo" +} +array(7) { ["lifetime"]=> int(3600) ["path"]=> @@ -130,6 +161,8 @@ array(6) { string(3) "foo" ["secure"]=> bool(true) + ["partitioned"]=> + bool(true) ["httponly"]=> bool(true) ["samesite"]=> diff --git a/ext/session/tests/session_regenerate_id_cookie.phpt b/ext/session/tests/session_regenerate_id_cookie.phpt index f1dc0727205d2..6516ad7061d10 100644 --- a/ext/session/tests/session_regenerate_id_cookie.phpt +++ b/ext/session/tests/session_regenerate_id_cookie.phpt @@ -55,7 +55,7 @@ ob_end_flush(); ?>'); $extra_arguments = getenv('TEST_PHP_EXTRA_ARGS'); -var_dump(`$php $extra_arguments -d session.name=PHPSESSID $file`); +var_dump(shell_exec("$php $extra_arguments -d session.name=PHPSESSID $file")); unlink($file); diff --git a/ext/session/tests/session_start_partitioned.phpt b/ext/session/tests/session_start_partitioned.phpt new file mode 100644 index 0000000000000..c2c1b33ae074a --- /dev/null +++ b/ext/session/tests/session_start_partitioned.phpt @@ -0,0 +1,31 @@ +--TEST-- +session_start() with partitioned cookies +--INI-- +session.use_strict_mode=0 +session.save_handler=files +session.save_path= +session.cookie_secure=0 +session.cookie_partitioned=0 +--EXTENSIONS-- +session +--SKIPIF-- + +--FILE-- + true])); +var_dump(session_start(['cookie_partitioned' => true, 'cookie_secure' => false])); +var_dump(session_start(['cookie_partitioned' => true, 'cookie_secure' => true])); + +ob_end_flush(); + +?> +--EXPECTF-- +Warning: session_start(): Partitioned session cookie cannot be used without also configuring it as secure in %s on line %d +bool(false) + +Warning: session_start(): Partitioned session cookie cannot be used without also configuring it as secure in %s on line %d +bool(false) +bool(true) diff --git a/ext/session/tests/session_start_partitioned_headers.phpt b/ext/session/tests/session_start_partitioned_headers.phpt new file mode 100644 index 0000000000000..6fa3815aa85d0 --- /dev/null +++ b/ext/session/tests/session_start_partitioned_headers.phpt @@ -0,0 +1,13 @@ +--TEST-- +session_start() with partitioned cookies - header test +--EXTENSIONS-- +session +--FILE-- + true, "partitioned" => true]); +session_start(); +?> +--EXPECTHEADERS-- +Set-Cookie: PHPSESSID=12345; path=/; secure; Partitioned +--EXPECT-- diff --git a/ext/session/tests/user_session_module/bug61728.phpt b/ext/session/tests/user_session_module/bug61728.phpt index fd79fa6b2bce4..152cf9f42beef 100644 --- a/ext/session/tests/user_session_module/bug61728.phpt +++ b/ext/session/tests/user_session_module/bug61728.phpt @@ -5,7 +5,7 @@ session --FILE-- args[0].value, &attribute_Deprecated_func_shmop_close_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_shmop_close_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_shmop_close_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_shmop_close_0_arg1; zend_string *attribute_Deprecated_func_shmop_close_0_arg1_str = zend_string_init("as Shmop objects are freed automatically", strlen("as Shmop objects are freed automatically"), 1); - ZVAL_STR(&attribute_Deprecated_func_shmop_close_0_arg1, attribute_Deprecated_func_shmop_close_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_shmop_close_0->args[1].value, &attribute_Deprecated_func_shmop_close_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_shmop_close_0->args[1].value, attribute_Deprecated_func_shmop_close_0_arg1_str); attribute_Deprecated_func_shmop_close_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index db1d002b66979..7abaee78666e7 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1528,10 +1528,10 @@ static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, /* Attributes in the xmlns namespace should be treated as namespace declarations too. */ if (attr->ns && xmlStrEqual(attr->ns->href, (const xmlChar *) "http://www.w3.org/2000/xmlns/")) { const char *prefix = attr->ns->prefix ? (const char *) attr->name : ""; - bool free; - xmlChar *href = php_libxml_attr_value(attr, &free); + bool should_free; + xmlChar *href = php_libxml_attr_value(attr, &should_free); sxe_add_namespace_name_raw(return_value, prefix, (const char *) href); - if (free) { + if (should_free) { xmlFree(href); } } diff --git a/ext/simplexml/tests/033.phpt b/ext/simplexml/tests/033.phpt index 6fd52750ee0bd..6d681d7695ca4 100644 --- a/ext/simplexml/tests/033.phpt +++ b/ext/simplexml/tests/033.phpt @@ -25,8 +25,8 @@ var_dump((bool)$foo); var_dump((bool)$people); var_dump((int)$foo); var_dump((int)$people); -var_dump((double)$foo); -var_dump((double)$people); +var_dump((float)$foo); +var_dump((float)$people); var_dump((string)$foo); var_dump((string)$people); var_dump((array)$foo); diff --git a/ext/simplexml/tests/bug54973.phpt b/ext/simplexml/tests/bug54973.phpt index 5c9f6ffaca229..ad8a986ff5678 100644 --- a/ext/simplexml/tests/bug54973.phpt +++ b/ext/simplexml/tests/bug54973.phpt @@ -11,8 +11,8 @@ var_dump($xml->number); $int = $xml->number / 1024 / 1024 / 1024; var_dump($int); -$double = (double) $xml->number / 1024 / 1024 / 1024; -var_dump($double); +$float = (float) $xml->number / 1024 / 1024 / 1024; +var_dump($float); ?> --EXPECT-- object(SimpleXMLElement)#2 (1) { diff --git a/ext/simplexml/tests/gh15837.phpt b/ext/simplexml/tests/gh15837.phpt index 302db064ee0e7..c654938e2c3c8 100644 --- a/ext/simplexml/tests/gh15837.phpt +++ b/ext/simplexml/tests/gh15837.phpt @@ -2,6 +2,8 @@ GH-15837 (Segmentation fault in ext/simplexml/simplexml.c) --CREDITS-- YuanchengJiang +--EXTENSIONS-- +simplexml --FILE-- doc, NULL, BAD_CAST("BOGUS"), NULL); } xmlAddChild(parent, ret); if (style == SOAP_ENCODED) { @@ -855,7 +855,7 @@ static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNo { xmlNodePtr ret, text; - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); @@ -937,7 +937,7 @@ static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNo { xmlNodePtr ret, text; - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); @@ -963,7 +963,7 @@ static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNo zval tmp; size_t i, j; - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); @@ -1066,7 +1066,7 @@ static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNode { xmlNodePtr ret; - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); @@ -1093,7 +1093,7 @@ static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNo zval tmp; char *str; - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); @@ -1141,7 +1141,7 @@ static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNode { xmlNodePtr ret; - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); @@ -1168,7 +1168,7 @@ static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNode { xmlNodePtr ret; - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); if (style == SOAP_ENCODED) { set_xsi_nil(ret); @@ -1306,12 +1306,12 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr } master_to_zval(&val, model->u.element->encode, r_node); } else if (model->u.element->fixed) { - xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlNodePtr dummy = xmlNewDocNode(node->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed)); master_to_zval(&val, model->u.element->encode, dummy); xmlFreeNode(dummy); } else if (model->u.element->def && !model->u.element->nillable) { - xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlNodePtr dummy = xmlNewDocNode(node->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def)); master_to_zval(&val, model->u.element->encode, dummy); xmlFreeNode(dummy); @@ -1331,12 +1331,12 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr } master_to_zval(&val, model->u.element->encode, node); } else if (model->u.element->fixed) { - xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlNodePtr dummy = xmlNewDocNode(node->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed)); master_to_zval(&val, model->u.element->encode, dummy); xmlFreeNode(dummy); } else if (model->u.element->def && !model->u.element->nillable) { - xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlNodePtr dummy = xmlNewDocNode(node->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def)); master_to_zval(&val, model->u.element->encode, dummy); xmlFreeNode(dummy); @@ -1541,7 +1541,7 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z xmlNodePtr dummy, text; zval data; - dummy = xmlNewNode(NULL, BAD_CAST("BOGUS")); + dummy = xmlNewDocNode(NULL, NULL, BAD_CAST("BOGUS"), NULL); text = xmlNewText(BAD_CAST(str_val)); xmlAddChild(dummy, text); ZVAL_NULL(&data); @@ -1646,7 +1646,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval * ZEND_HASH_FOREACH_VAL(ht, val) { ZVAL_DEREF(val); if (Z_TYPE_P(val) == IS_NULL && model->u.element->nillable) { - property = xmlNewNode(NULL, BAD_CAST("BOGUS")); + property = xmlNewDocNode(node->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(node, property); set_xsi_nil(property); } else { @@ -1666,7 +1666,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval * } ZEND_HASH_FOREACH_END(); } else { if (Z_TYPE_P(data) == IS_NULL && model->u.element->nillable) { - property = xmlNewNode(NULL, BAD_CAST("BOGUS")); + property = xmlNewDocNode(node->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(node, property); set_xsi_nil(property); } else if (Z_TYPE_P(data) == IS_NULL && model->min_occurs == 0) { @@ -1688,7 +1688,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval * } return 1; } else if (strict && model->u.element->nillable && model->min_occurs > 0) { - property = xmlNewNode(NULL, BAD_CAST(model->u.element->name)); + property = xmlNewDocNode(node->doc, NULL, BAD_CAST(model->u.element->name), NULL); xmlAddChild(node, property); set_xsi_nil(property); if (style == SOAP_LITERAL && @@ -1816,7 +1816,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo sdlTypePtr sdlType = type->sdl_type; if (!data || Z_TYPE_P(data) == IS_NULL) { - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); if (style == SOAP_ENCODED) { set_xsi_nil(xmlParam); @@ -1851,11 +1851,11 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo } else if (prop == NULL) { xmlParam = master_to_xml(enc, data, style, parent); } else { - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); } } else { - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); } } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION && @@ -1877,12 +1877,12 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo } else if (prop == NULL) { xmlParam = master_to_xml(sdlType->encode, data, style, parent); } else { - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); } } } else { - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); } @@ -1903,7 +1903,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo xmlNodePtr property; ZVAL_DEREF(val); if (Z_TYPE_P(val) == IS_NULL && array_el->nillable) { - property = xmlNewNode(NULL, BAD_CAST("BOGUS")); + property = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(xmlParam, property); set_xsi_nil(property); } else { @@ -1924,6 +1924,11 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo sdlAttributePtr attr; zval *zattr, rv; + /* Attributes can't refer to other attributes as there's nothing to attach the href to. */ + HashTable **ref_map = &SOAP_GLOBAL(ref_map); + HashTable *old_ref_map = *ref_map; + *ref_map = NULL; + ZEND_HASH_FOREACH_PTR(sdlType->attributes, attr) { if (attr->name) { zattr = get_zval_property(data, attr->name, &rv); @@ -1953,13 +1958,15 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo } } } ZEND_HASH_FOREACH_END(); + + *ref_map = old_ref_map; } } if (style == SOAP_ENCODED) { set_ns_and_type(xmlParam, type); } } else { - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); if (soap_check_zval_ref(data, xmlParam)) { @@ -2159,7 +2166,7 @@ static void add_xml_array_elements(xmlNodePtr xmlParam, if (dimension == 1) { while (j < dims[0]) { - xparam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xparam = xmlNewDocNode(xmlParam->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(xmlParam, xparam); if (type) { @@ -2186,7 +2193,7 @@ static void add_xml_array_elements(xmlNodePtr xmlParam, if (dimension == 1) { xmlNodePtr xparam; - xparam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xparam = xmlNewDocNode(xmlParam->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(xmlParam, xparam); if (type) { xmlNodeSetName(xparam, BAD_CAST(type->name)); @@ -2219,7 +2226,7 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod ZVAL_UNDEF(&array_copy); soap_version = SOAP_GLOBAL(soap_version); - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); if (!data || Z_TYPE_P(data) == IS_NULL) { @@ -2714,7 +2721,7 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP xmlNodePtr xparam, item; xmlNodePtr key; - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); FIND_ZVAL_NULL(data, xmlParam, style); @@ -2727,9 +2734,9 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP GC_TRY_PROTECT_RECURSION(Z_ARRVAL_P(data)); ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(data), int_val, key_val, temp_data) { - item = xmlNewNode(NULL, BAD_CAST("item")); + item = xmlNewDocNode(parent->doc, NULL, BAD_CAST("item"), NULL); xmlAddChild(xmlParam, item); - key = xmlNewNode(NULL, BAD_CAST("key")); + key = xmlNewDocNode(parent->doc, NULL, BAD_CAST("key"), NULL); xmlAddChild(item,key); if (key_val) { if (style == SOAP_ENCODED) { @@ -2920,7 +2927,7 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma xmlNodePtr xmlParam; - xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS")); + xmlParam = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, xmlParam); FIND_ZVAL_NULL(data, xmlParam, style); @@ -3052,9 +3059,15 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP } ZEND_HASH_FOREACH_END(); } - ret = xmlNewNode(NULL, BAD_CAST("BOGUS")); + ret = xmlNewDocNode(parent->doc, NULL, BAD_CAST("BOGUS"), NULL); xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); + + /* Literals are unique and can't refer to other references via attributes. */ + HashTable **ref_map = &SOAP_GLOBAL(ref_map); + HashTable *old_ref_map = *ref_map; + *ref_map = NULL; + if (Z_TYPE_P(data) == IS_ARRAY) { zval *tmp; smart_str list = {0}; @@ -3129,6 +3142,7 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP zval_ptr_dtor_str(&tmp); } } + *ref_map = old_ref_map; return ret; } diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 84a10368d22fe..ac5f0f0f9d1ed 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -18,6 +18,7 @@ #include "php_soap.h" #include "ext/hash/php_hash.h" /* For php_hash_bin2hex() */ +#include "ext/uri/php_uri.h" static char *get_http_header_value_nodup(char *headers, char *type, size_t *len); static char *get_http_header_value(char *headers, char *type); @@ -162,7 +163,7 @@ void http_context_headers(php_stream_context* context, } } -static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, php_stream_context *context, int *use_proxy) +static php_stream* http_connect(zval* this_ptr, php_uri *uri, int use_ssl, php_stream_context *context, int *use_proxy) { php_stream *stream; zval *tmp, ssl_proxy_peer_name; @@ -182,8 +183,8 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, ph port = Z_LVAL_P(proxy_port); *use_proxy = 1; } else { - host = ZSTR_VAL(phpurl->host); - port = phpurl->port; + host = ZSTR_VAL(uri->host); + port = uri->port; } tmp = Z_CLIENT_CONNECTION_TIMEOUT_P(this_ptr); @@ -247,21 +248,21 @@ static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, ph /* Set peer_name or name verification will try to use the proxy server name */ if (!context || (tmp = php_stream_context_get_option(context, "ssl", "peer_name")) == NULL) { - ZVAL_STR_COPY(&ssl_proxy_peer_name, phpurl->host); + ZVAL_STR_COPY(&ssl_proxy_peer_name, uri->host); php_stream_context_set_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name", &ssl_proxy_peer_name); zval_ptr_dtor(&ssl_proxy_peer_name); } smart_str_append_const(&soap_headers, "CONNECT "); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); smart_str_append_const(&soap_headers, " HTTP/1.1\r\n"); smart_str_append_const(&soap_headers, "Host: "); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); - if (phpurl->port != 80) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); + if (uri->port != 80) { smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); } smart_str_append_const(&soap_headers, "\r\n"); proxy_authentication(this_ptr, &soap_headers); @@ -335,18 +336,15 @@ static bool in_domain(const zend_string *host, const zend_string *domain) } } -int make_http_soap_request(zval *this_ptr, - zend_string *buf, - char *location, - char *soapaction, - int soap_version, - zval *return_value) -{ +int make_http_soap_request( + zval *this_ptr, zend_string *buf, zend_string *location, char *soapaction, + int soap_version, zend_string *uri_parser_class, zval *return_value +) { zend_string *request; smart_str soap_headers = {0}; smart_str soap_headers_z = {0}; size_t err; - php_url *phpurl = NULL; + php_uri *uri = NULL; php_stream *stream; zval *tmp; int use_proxy = 0; @@ -432,8 +430,13 @@ int make_http_soap_request(zval *this_ptr, stream = NULL; } - if (location != NULL && location[0] != '\000') { - phpurl = php_url_parse(location); + if (location != NULL && ZSTR_VAL(location)[0] != '\000') { + const php_uri_parser *uri_parser = php_uri_get_parser(uri_parser_class); + if (uri_parser == NULL) { + zend_argument_value_error(6, "must be a valid URI parser name"); + return FALSE; + } + uri = php_uri_parse_to_struct(uri_parser, ZSTR_VAL(location), ZSTR_LEN(location), PHP_URI_COMPONENT_READ_MODE_RAW, true); } tmp = Z_CLIENT_STREAM_CONTEXT_P(this_ptr); @@ -450,8 +453,10 @@ int make_http_soap_request(zval *this_ptr, } try_again: - if (phpurl == NULL || phpurl->host == NULL) { - if (phpurl != NULL) {php_url_free(phpurl);} + if (uri == NULL || uri->host == NULL) { + if (uri != NULL) { + php_uri_struct_free(uri); + } if (request != buf) { zend_string_release_ex(request, 0); } @@ -462,10 +467,10 @@ int make_http_soap_request(zval *this_ptr, } use_ssl = 0; - if (phpurl->scheme != NULL && zend_string_equals_literal(phpurl->scheme, "https")) { + if (uri->scheme != NULL && zend_string_equals_literal(uri->scheme, "https")) { use_ssl = 1; - } else if (phpurl->scheme == NULL || !zend_string_equals_literal(phpurl->scheme, "http")) { - php_url_free(phpurl); + } else if (uri->scheme == NULL || !zend_string_equals_literal(uri->scheme, "http")) { + php_uri_struct_free(uri); if (request != buf) { zend_string_release_ex(request, 0); } @@ -478,7 +483,7 @@ int make_http_soap_request(zval *this_ptr, old_allow_url_fopen = PG(allow_url_fopen); PG(allow_url_fopen) = 1; if (use_ssl && php_stream_locate_url_wrapper("https://", NULL, STREAM_LOCATE_WRAPPERS_ONLY) == NULL) { - php_url_free(phpurl); + php_uri_struct_free(uri); if (request != buf) { zend_string_release_ex(request, 0); } @@ -489,27 +494,27 @@ int make_http_soap_request(zval *this_ptr, return FALSE; } - if (phpurl->port == 0) { - phpurl->port = use_ssl ? 443 : 80; + if (uri->port == 0) { + uri->port = use_ssl ? 443 : 80; } /* Check if request to the same host */ if (stream != NULL) { - php_url *orig; + php_uri *orig; tmp = Z_CLIENT_HTTPURL_P(this_ptr); if (Z_TYPE_P(tmp) == IS_OBJECT && instanceof_function(Z_OBJCE_P(tmp), soap_url_class_entry) && - (orig = Z_SOAP_URL_P(tmp)->url) != NULL && + (orig = Z_SOAP_URL_P(tmp)->uri) != NULL && ((use_proxy && !use_ssl) || (((use_ssl && orig->scheme != NULL && zend_string_equals_literal(orig->scheme, "https")) || (!use_ssl && orig->scheme == NULL) || (!use_ssl && !zend_string_equals_literal(orig->scheme, "https"))) && - zend_string_equals(orig->host, phpurl->host) && - orig->port == phpurl->port))) { + zend_string_equals(orig->host, uri->host) && + orig->port == uri->port))) { } else { + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr)); - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); stream = NULL; use_proxy = 0; } @@ -517,23 +522,21 @@ int make_http_soap_request(zval *this_ptr, /* Check if keep-alive connection is still opened */ if (stream != NULL && php_stream_eof(stream)) { + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr)); - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); stream = NULL; use_proxy = 0; } if (!stream) { - stream = http_connect(this_ptr, phpurl, use_ssl, context, &use_proxy); + stream = http_connect(this_ptr, uri, use_ssl, context, &use_proxy); if (stream) { - php_stream_auto_cleanup(stream); - ZVAL_RES(Z_CLIENT_HTTPSOCKET_P(this_ptr), stream->res); - GC_ADDREF(stream->res); + php_stream_to_zval(stream, Z_CLIENT_HTTPSOCKET_P(this_ptr)); ZVAL_LONG(Z_CLIENT_USE_PROXY_P(this_ptr), use_proxy); } else { - php_url_free(phpurl); + php_uri_struct_free(uri); if (request != buf) { zend_string_release_ex(request, 0); } @@ -558,7 +561,7 @@ int make_http_soap_request(zval *this_ptr, object_init_ex(url_zval, soap_url_class_entry); soap_url_object *url_obj = Z_SOAP_URL_P(url_zval); - url_obj->url = phpurl; + url_obj->uri = uri; if (context && (tmp = php_stream_context_get_option(context, "http", "protocol_version")) != NULL && @@ -571,24 +574,24 @@ int make_http_soap_request(zval *this_ptr, smart_str_append_const(&soap_headers, "POST "); if (use_proxy && !use_ssl) { - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->scheme)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->scheme)); smart_str_append_const(&soap_headers, "://"); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); } - if (phpurl->path) { - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->path)); + if (uri->path) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->path)); } else { smart_str_appendc(&soap_headers, '/'); } - if (phpurl->query) { + if (uri->query) { smart_str_appendc(&soap_headers, '?'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->query)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->query)); } - if (phpurl->fragment) { + if (uri->fragment) { smart_str_appendc(&soap_headers, '#'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->fragment)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->fragment)); } if (http_1_1) { smart_str_append_const(&soap_headers, " HTTP/1.1\r\n"); @@ -596,10 +599,10 @@ int make_http_soap_request(zval *this_ptr, smart_str_append_const(&soap_headers, " HTTP/1.0\r\n"); } smart_str_append_const(&soap_headers, "Host: "); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->host)); - if (phpurl->port != (use_ssl?443:80)) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->host)); + if (uri->port != (use_ssl?443:80)) { smart_str_appendc(&soap_headers, ':'); - smart_str_append_unsigned(&soap_headers, phpurl->port); + smart_str_append_unsigned(&soap_headers, uri->port); } if (!http_1_1 || Z_TYPE_P(Z_CLIENT_KEEP_ALIVE_P(this_ptr)) == IS_FALSE) { smart_str_append_const(&soap_headers, "\r\n" @@ -686,10 +689,10 @@ int make_http_soap_request(zval *this_ptr, if (UNEXPECTED(php_random_bytes_throw(&nonce, sizeof(nonce)) != SUCCESS)) { ZEND_ASSERT(EG(exception)); + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr)); - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); smart_str_free(&soap_headers_z); smart_str_free(&soap_headers); efree(http_msg); @@ -741,14 +744,14 @@ int make_http_soap_request(zval *this_ptr, PHP_MD5Init(&md5ctx); PHP_MD5Update(&md5ctx, (unsigned char*)"POST:", sizeof("POST:")-1); - if (phpurl->path) { - PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(phpurl->path), ZSTR_LEN(phpurl->path)); + if (uri->path) { + PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(uri->path), ZSTR_LEN(uri->path)); } else { PHP_MD5Update(&md5ctx, (unsigned char*)"/", 1); } - if (phpurl->query) { + if (uri->query) { PHP_MD5Update(&md5ctx, (unsigned char*)"?", 1); - PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(phpurl->query), ZSTR_LEN(phpurl->query)); + PHP_MD5Update(&md5ctx, (unsigned char*)ZSTR_VAL(uri->query), ZSTR_LEN(uri->query)); } PHP_MD5Final(hash, &md5ctx); @@ -789,18 +792,18 @@ int make_http_soap_request(zval *this_ptr, smart_str_appendl(&soap_headers, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); } smart_str_append_const(&soap_headers, "\", uri=\""); - if (phpurl->path) { - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->path)); + if (uri->path) { + smart_str_appends(&soap_headers, ZSTR_VAL(uri->path)); } else { smart_str_appendc(&soap_headers, '/'); } - if (phpurl->query) { + if (uri->query) { smart_str_appendc(&soap_headers, '?'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->query)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->query)); } - if (phpurl->fragment) { + if (uri->fragment) { smart_str_appendc(&soap_headers, '#'); - smart_str_appends(&soap_headers, ZSTR_VAL(phpurl->fragment)); + smart_str_appends(&soap_headers, ZSTR_VAL(uri->fragment)); } if ((tmp = zend_hash_str_find(Z_ARRVAL_P(digest), "qop", sizeof("qop")-1)) != NULL && Z_TYPE_P(tmp) == IS_STRING) { @@ -867,10 +870,10 @@ int make_http_soap_request(zval *this_ptr, zval *tmp; if (((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 1)) == NULL || Z_TYPE_P(tmp) != IS_STRING || - strncmp(phpurl->path?ZSTR_VAL(phpurl->path):"/",Z_STRVAL_P(tmp),Z_STRLEN_P(tmp)) == 0) && + strncmp(uri->path?ZSTR_VAL(uri->path):"/",Z_STRVAL_P(tmp),Z_STRLEN_P(tmp)) == 0) && ((tmp = zend_hash_index_find(Z_ARRVAL_P(data), 2)) == NULL || Z_TYPE_P(tmp) != IS_STRING || - in_domain(phpurl->host, Z_STR_P(tmp))) && + in_domain(uri->host, Z_STR_P(tmp))) && (use_ssl || (tmp = zend_hash_index_find(Z_ARRVAL_P(data), 3)) == NULL)) { if (!first_cookie) { smart_str_appends(&soap_headers, "; "); @@ -904,10 +907,10 @@ int make_http_soap_request(zval *this_ptr, if (request != buf) { zend_string_release_ex(request, 0); } + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr)); - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL, SOAP_GLOBAL(lang_en)); smart_str_free(&soap_headers_z); efree(http_msg); @@ -929,9 +932,9 @@ int make_http_soap_request(zval *this_ptr, if (request != buf) { zend_string_release_ex(request, 0); } + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL, SOAP_GLOBAL(lang_en)); smart_str_free(&soap_headers_z); efree(http_msg); @@ -982,12 +985,12 @@ int make_http_soap_request(zval *this_ptr, if (request != buf) { zend_string_release_ex(request, 0); } + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); if (http_headers) { zend_string_release_ex(http_headers, 0); } - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); if (http_msg) { efree(http_msg); } @@ -1049,15 +1052,15 @@ int make_http_soap_request(zval *this_ptr, } } if (!zend_hash_index_exists(Z_ARRVAL(zcookie), 1)) { - char *t = phpurl->path?ZSTR_VAL(phpurl->path):"/"; + char *t = uri->path?ZSTR_VAL(uri->path):"/"; char *c = strrchr(t, '/'); if (c) { add_index_stringl(&zcookie, 1, t, c-t); } } if (!zend_hash_index_exists(Z_ARRVAL(zcookie), 2)) { - add_index_str(&zcookie, 2, phpurl->host); - GC_ADDREF(phpurl->host); + add_index_str(&zcookie, 2, uri->host); + GC_ADDREF(uri->host); } zend_symtable_update(Z_ARRVAL_P(cookies), name.s, &zcookie); @@ -1117,10 +1120,10 @@ int make_http_soap_request(zval *this_ptr, if (request != buf) { zend_string_release_ex(request, 0); } + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); zend_string_release_ex(http_headers, 0); - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL, SOAP_GLOBAL(lang_en)); if (http_msg) { efree(http_msg); @@ -1134,9 +1137,9 @@ int make_http_soap_request(zval *this_ptr, } if (http_close) { + ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr)); php_stream_close(stream); - convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); - convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); + ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr)); stream = NULL; } @@ -1145,39 +1148,46 @@ int make_http_soap_request(zval *this_ptr, char *loc; if ((loc = get_http_header_value(ZSTR_VAL(http_headers), "Location:")) != NULL) { - php_url *new_url = php_url_parse(loc); + const php_uri_parser *uri_parser = php_uri_get_parser(uri_parser_class); + if (uri_parser == NULL) { + efree(loc); + zend_argument_value_error(6, "must be a valid URI parser name"); + return FALSE; + } - if (new_url != NULL) { + php_uri *new_uri = php_uri_parse_to_struct(uri_parser, loc, strlen(loc), PHP_URI_COMPONENT_READ_MODE_RAW, true); + efree(loc); + + if (new_uri != NULL) { zend_string_release_ex(http_headers, 0); zend_string_release_ex(http_body, 0); - efree(loc); - if (new_url->scheme == NULL && new_url->path != NULL) { - new_url->scheme = phpurl->scheme ? zend_string_copy(phpurl->scheme) : NULL; - new_url->host = phpurl->host ? zend_string_copy(phpurl->host) : NULL; - new_url->port = phpurl->port; - if (new_url->path && ZSTR_VAL(new_url->path)[0] != '/') { - if (phpurl->path) { - char *t = ZSTR_VAL(phpurl->path); + if (new_uri->scheme == NULL && new_uri->path != NULL) { + new_uri->scheme = new_uri->scheme ? zend_string_copy(new_uri->scheme) : NULL; + new_uri->host = new_uri->host ? zend_string_copy(new_uri->host) : NULL; + new_uri->port = new_uri->port; + if (new_uri->path && ZSTR_VAL(new_uri->path)[0] != '/') { + if (new_uri->path) { + char *t = ZSTR_VAL(new_uri->path); char *p = strrchr(t, '/'); if (p) { - zend_string *s = zend_string_alloc((p - t) + ZSTR_LEN(new_url->path) + 2, 0); + zend_string *s = zend_string_alloc((p - t) + ZSTR_LEN(new_uri->path) + 2, 0); strncpy(ZSTR_VAL(s), t, (p - t) + 1); ZSTR_VAL(s)[(p - t) + 1] = 0; - strcat(ZSTR_VAL(s), ZSTR_VAL(new_url->path)); - zend_string_release_ex(new_url->path, 0); - new_url->path = s; + strcat(ZSTR_VAL(s), ZSTR_VAL(new_uri->path)); + zend_string_release_ex(new_uri->path, 0); + new_uri->path = s; } } else { - zend_string *s = zend_string_alloc(ZSTR_LEN(new_url->path) + 2, 0); + zend_string *s = zend_string_alloc(ZSTR_LEN(new_uri->path) + 2, 0); ZSTR_VAL(s)[0] = '/'; ZSTR_VAL(s)[1] = 0; - strcat(ZSTR_VAL(s), ZSTR_VAL(new_url->path)); - zend_string_release_ex(new_url->path, 0); - new_url->path = s; + strcat(ZSTR_VAL(s), ZSTR_VAL(new_uri->path)); + zend_string_release_ex(new_uri->path, 0); + new_uri->path = s; } } } - phpurl = new_url; + uri = new_uri; if (--redirect_max < 1) { add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL, SOAP_GLOBAL(lang_en)); @@ -1237,20 +1247,20 @@ int make_http_soap_request(zval *this_ptr, } if (Z_TYPE(digest) != IS_UNDEF) { - php_url *new_url = emalloc(sizeof(php_url)); + php_uri *new_uri = emalloc(sizeof(php_uri)); zval_ptr_dtor(Z_CLIENT_DIGEST_P(this_ptr)); ZVAL_COPY_VALUE(Z_CLIENT_DIGEST_P(this_ptr), &digest); - *new_url = *phpurl; - if (phpurl->scheme) phpurl->scheme = zend_string_copy(phpurl->scheme); - if (phpurl->user) phpurl->user = zend_string_copy(phpurl->user); - if (phpurl->pass) phpurl->pass = zend_string_copy(phpurl->pass); - if (phpurl->host) phpurl->host = zend_string_copy(phpurl->host); - if (phpurl->path) phpurl->path = zend_string_copy(phpurl->path); - if (phpurl->query) phpurl->query = zend_string_copy(phpurl->query); - if (phpurl->fragment) phpurl->fragment = zend_string_copy(phpurl->fragment); - phpurl = new_url; + *new_uri = *uri; + if (uri->scheme) uri->scheme = zend_string_copy(uri->scheme); + if (uri->user) uri->user = zend_string_copy(uri->user); + if (uri->password) uri->password = zend_string_copy(uri->password); + if (uri->host) uri->host = zend_string_copy(uri->host); + if (uri->path) uri->path = zend_string_copy(uri->path); + if (uri->query) uri->query = zend_string_copy(uri->query); + if (uri->fragment) uri->fragment = zend_string_copy(uri->fragment); + uri = new_uri; efree(auth); zend_string_release_ex(http_headers, 0); @@ -1296,21 +1306,19 @@ int make_http_soap_request(zval *this_ptr, /* Decompress response */ content_encoding = get_http_header_value(ZSTR_VAL(http_headers), "Content-Encoding:"); if (content_encoding) { - zval func; zval retval; zval params[1]; + zend_function *decompression_fn; /* Warning: the zlib function names are chosen in an unfortunate manner. * Check zlib.c to see how a function corresponds with a particular format. */ if ((strcmp(content_encoding,"gzip") == 0 || strcmp(content_encoding,"x-gzip") == 0) && - zend_hash_str_exists(EG(function_table), "gzdecode", sizeof("gzdecode")-1)) { - ZVAL_STRING(&func, "gzdecode"); - ZVAL_STR_COPY(¶ms[0], http_body); + (decompression_fn = zend_hash_str_find_ptr(EG(function_table), "gzdecode", sizeof("gzdecode")-1))) { + ZVAL_STR(¶ms[0], http_body); } else if (strcmp(content_encoding,"deflate") == 0 && - zend_hash_str_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress")-1)) { - ZVAL_STRING(&func, "gzuncompress"); - ZVAL_STR_COPY(¶ms[0], http_body); + (decompression_fn = zend_hash_str_find_ptr(EG(function_table), "gzuncompress", sizeof("gzuncompress")-1))) { + ZVAL_STR(¶ms[0], http_body); } else { efree(content_encoding); zend_string_release_ex(http_headers, 0); @@ -1321,15 +1329,11 @@ int make_http_soap_request(zval *this_ptr, add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL, SOAP_GLOBAL(lang_en)); return FALSE; } - if (call_user_function(CG(function_table), (zval*)NULL, &func, &retval, 1, params) == SUCCESS && - Z_TYPE(retval) == IS_STRING) { - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(&func); + zend_call_known_function(decompression_fn, NULL, NULL, &retval, 1, params, NULL); + if (Z_TYPE(retval) == IS_STRING) { zend_string_release_ex(http_body, 0); ZVAL_COPY_VALUE(return_value, &retval); } else { - zval_ptr_dtor(¶ms[0]); - zval_ptr_dtor(&func); zval_ptr_dtor(&retval); efree(content_encoding); zend_string_release_ex(http_headers, 0); diff --git a/ext/soap/php_http.h b/ext/soap/php_http.h index df24c0d26fa84..7716e86720bd7 100644 --- a/ext/soap/php_http.h +++ b/ext/soap/php_http.h @@ -19,12 +19,10 @@ #ifndef PHP_HTTP_H #define PHP_HTTP_H -int make_http_soap_request(zval *this_ptr, - zend_string *request, - char *location, - char *soapaction, - int soap_version, - zval *response); +int make_http_soap_request( + zval *this_ptr, zend_string *buf, zend_string *location, char *soapaction, + int soap_version, zend_string *uri_parser_class, zval *return_value +); int proxy_authentication(zval* this_ptr, smart_str* soap_headers); int basic_authentication(zval* this_ptr, smart_str* soap_headers); diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h index 98e3d4af6f19d..48f8fb50591cb 100644 --- a/ext/soap/php_soap.h +++ b/ext/soap/php_soap.h @@ -27,6 +27,7 @@ #include "zend_smart_str.h" #include "php_ini.h" #include "SAPI.h" +#include "ext/uri/php_uri.h" #include #include @@ -216,45 +217,46 @@ static zend_always_inline zval *php_soap_deref(zval *zv) { return zv; } -#define Z_CLIENT_URI_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0)) -#define Z_CLIENT_STYLE_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1)) -#define Z_CLIENT_USE_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2)) -#define Z_CLIENT_LOCATION_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3)) -#define Z_CLIENT_TRACE_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 4)) -#define Z_CLIENT_COMPRESSION_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5)) -#define Z_CLIENT_SDL_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6)) -#define Z_CLIENT_TYPEMAP_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 7)) -#define Z_CLIENT_HTTPSOCKET_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 8)) -#define Z_CLIENT_HTTPURL_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 9)) -#define Z_CLIENT_LOGIN_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 10)) -#define Z_CLIENT_PASSWORD_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 11)) -#define Z_CLIENT_USE_DIGEST_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 12)) -#define Z_CLIENT_DIGEST_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 13)) -#define Z_CLIENT_PROXY_HOST_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 14)) -#define Z_CLIENT_PROXY_PORT_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 15)) -#define Z_CLIENT_PROXY_LOGIN_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 16)) -#define Z_CLIENT_PROXY_PASSWORD_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 17)) -#define Z_CLIENT_EXCEPTIONS_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 18)) -#define Z_CLIENT_ENCODING_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 19)) -#define Z_CLIENT_CLASSMAP_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 20)) -#define Z_CLIENT_FEATURES_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 21)) -#define Z_CLIENT_CONNECTION_TIMEOUT_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 22)) -#define Z_CLIENT_STREAM_CONTEXT_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 23)) -#define Z_CLIENT_USER_AGENT_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 24)) -#define Z_CLIENT_KEEP_ALIVE_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 25)) -#define Z_CLIENT_SSL_METHOD_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 26)) -#define Z_CLIENT_SOAP_VERSION_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 27)) -#define Z_CLIENT_USE_PROXY_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 28)) -#define Z_CLIENT_COOKIES_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 29)) -#define Z_CLIENT_DEFAULT_HEADERS_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 30)) -#define Z_CLIENT_SOAP_FAULT_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 31)) -#define Z_CLIENT_LAST_REQUEST_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 32)) -#define Z_CLIENT_LAST_RESPONSE_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 33)) -#define Z_CLIENT_LAST_REQUEST_HEADERS_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 34)) -#define Z_CLIENT_LAST_RESPONSE_HEADERS_P(zv) php_soap_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 35)) +/* SoapClient's properties are all private and can't be references */ +#define Z_CLIENT_URI_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 0) +#define Z_CLIENT_STYLE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 1) +#define Z_CLIENT_USE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 2) +#define Z_CLIENT_LOCATION_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 3) +#define Z_CLIENT_TRACE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 4) +#define Z_CLIENT_COMPRESSION_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 5) +#define Z_CLIENT_SDL_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 6) +#define Z_CLIENT_TYPEMAP_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 7) +#define Z_CLIENT_HTTPSOCKET_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 8) +#define Z_CLIENT_HTTPURL_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 9) +#define Z_CLIENT_LOGIN_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 10) +#define Z_CLIENT_PASSWORD_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 11) +#define Z_CLIENT_USE_DIGEST_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 12) +#define Z_CLIENT_DIGEST_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 13) +#define Z_CLIENT_PROXY_HOST_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 14) +#define Z_CLIENT_PROXY_PORT_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 15) +#define Z_CLIENT_PROXY_LOGIN_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 16) +#define Z_CLIENT_PROXY_PASSWORD_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 17) +#define Z_CLIENT_EXCEPTIONS_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 18) +#define Z_CLIENT_ENCODING_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 19) +#define Z_CLIENT_CLASSMAP_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 20) +#define Z_CLIENT_FEATURES_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 21) +#define Z_CLIENT_CONNECTION_TIMEOUT_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 22) +#define Z_CLIENT_STREAM_CONTEXT_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 23) +#define Z_CLIENT_USER_AGENT_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 24) +#define Z_CLIENT_KEEP_ALIVE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 25) +#define Z_CLIENT_SSL_METHOD_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 26) +#define Z_CLIENT_SOAP_VERSION_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 27) +#define Z_CLIENT_USE_PROXY_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 28) +#define Z_CLIENT_COOKIES_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 29) +#define Z_CLIENT_DEFAULT_HEADERS_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 30) +#define Z_CLIENT_SOAP_FAULT_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 31) +#define Z_CLIENT_LAST_REQUEST_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 32) +#define Z_CLIENT_LAST_RESPONSE_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 33) +#define Z_CLIENT_LAST_REQUEST_HEADERS_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 34) +#define Z_CLIENT_LAST_RESPONSE_HEADERS_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 35) typedef struct soap_url_object { - php_url *url; + php_uri *uri; zend_object std; } soap_url_object; diff --git a/ext/soap/soap.c b/ext/soap/soap.c index cdb0216ebcf83..167dd4bb30af8 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -21,6 +21,7 @@ #endif #include "php_soap.h" #include "ext/session/php_session.h" +#include "zend_attributes.h" #include "soap_arginfo.h" #include "zend_exceptions.h" #include "zend_interfaces.h" @@ -232,9 +233,9 @@ static void soap_url_object_free(zend_object *obj) { soap_url_object *url_obj = soap_url_object_fetch(obj); - if (url_obj->url) { - php_url_free(url_obj->url); - url_obj->url = NULL; + if (url_obj->uri) { + php_uri_struct_free(url_obj->uri); + url_obj->uri = NULL; } zend_object_std_dtor(&url_obj->std); @@ -452,7 +453,6 @@ static void php_soap_init_globals(zend_soap_globals *soap_globals) soap_globals->soap_version = SOAP_1_1; soap_globals->mem_cache = NULL; soap_globals->ref_map = NULL; - soap_globals->lang_en = zend_string_init_interned(ZEND_STRL("en"), true); } PHP_MSHUTDOWN_FUNCTION(soap) @@ -552,6 +552,8 @@ PHP_MINIT_FUNCTION(soap) old_error_handler = zend_error_cb; zend_error_cb = soap_error_handler; + SOAP_GLOBAL(lang_en) = zend_string_init_interned(ZEND_STRL("en"), true); + return SUCCESS; } @@ -1011,7 +1013,13 @@ PHP_METHOD(SoapServer, __construct) service->soap_functions.ft = zend_new_array(0); if (wsdl) { - service->sdl = get_sdl(ZEND_THIS, ZSTR_VAL(wsdl), cache_wsdl); + zend_try { + service->sdl = get_sdl(ZEND_THIS, ZSTR_VAL(wsdl), cache_wsdl); + } zend_catch { + xmlCharEncCloseFunc(service->encoding); + service->encoding = NULL; + zend_bailout(); + } zend_end_try(); if (service->uri == NULL) { if (service->sdl->target_ns) { service->uri = estrdup(service->sdl->target_ns); @@ -2782,28 +2790,28 @@ PHP_METHOD(SoapClient, __getLastResponseHeaders) /* {{{ SoapClient::__doRequest() */ PHP_METHOD(SoapClient, __doRequest) { - zend_string *buf; - char *location, *action; - size_t location_size, action_size; + zend_string *buf, *location, *uri_parser_class = NULL; + char *action; + size_t action_size; zend_long version; bool one_way = 0; zval *this_ptr = ZEND_THIS; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sssl|b", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSsl|bS!", &buf, - &location, &location_size, + &location, &action, &action_size, - &version, &one_way) == FAILURE) { + &version, &one_way, &uri_parser_class) == FAILURE) { RETURN_THROWS(); } if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) { one_way = 0; } if (one_way) { - if (make_http_soap_request(this_ptr, buf, location, action, version, NULL)) { + if (make_http_soap_request(this_ptr, buf, location, action, version, uri_parser_class, NULL)) { RETURN_EMPTY_STRING(); } - } else if (make_http_soap_request(this_ptr, buf, location, action, version, + } else if (make_http_soap_request(this_ptr, buf, location, action, version, uri_parser_class, return_value)) { return; } @@ -3715,7 +3723,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, const char *fu if (version == SOAP_1_1) { tmp = Z_FAULT_CODE_P(ret); if (Z_TYPE_P(tmp) == IS_STRING) { - xmlNodePtr node = xmlNewNode(NULL, BAD_CAST("faultcode")); + xmlNodePtr node = xmlNewDocNode(doc, NULL, BAD_CAST("faultcode"), NULL); zend_string *str = php_escape_html_entities((unsigned char*)Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 0, 0, NULL); xmlAddChild(param, node); if (fault_ns) { @@ -3779,7 +3787,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, const char *fu if (Z_TYPE_P(tmp) > IS_NULL) { detail = tmp; } - node = xmlNewNode(NULL, BAD_CAST(detail_name)); + node = xmlNewDocNode(doc, NULL, BAD_CAST(detail_name), NULL); xmlAddChild(param, node); zend_hash_internal_pointer_reset(fault->details); @@ -4111,7 +4119,7 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function h = master_to_xml(enc, data, hdr_use, head); xmlNodeSetName(h, BAD_CAST(Z_STRVAL_P(name))); } else { - h = xmlNewNode(NULL, BAD_CAST(Z_STRVAL_P(name))); + h = xmlNewDocNode(doc, NULL, BAD_CAST(Z_STRVAL_P(name)), NULL); xmlAddChild(head, h); } nsptr = encode_add_ns(h, Z_STRVAL_P(ns)); @@ -4204,8 +4212,10 @@ static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, const char *param } xmlParam = master_to_xml(enc, val, style, parent); zval_ptr_dtor(&defval); - if (!strcmp((char*)xmlParam->name, "BOGUS")) { - xmlNodeSetName(xmlParam, BAD_CAST(paramName)); + if (xmlParam != NULL) { + if (xmlParam->name == NULL || strcmp((char*)xmlParam->name, "BOGUS") == 0) { + xmlNodeSetName(xmlParam, BAD_CAST(paramName)); + } } return xmlParam; } diff --git a/ext/soap/soap.stub.php b/ext/soap/soap.stub.php index 2520bd1346963..851b32042bd19 100644 --- a/ext/soap/soap.stub.php +++ b/ext/soap/soap.stub.php @@ -44,8 +44,8 @@ final class Sdl /** * @var int * @cvalue SOAP_FUNCTIONS_ALL - * @deprecated since 8.4 */ + #[\Deprecated(since: '8.4', message: 'as enabling all functions is a possible security concern')] const SOAP_FUNCTIONS_ALL = UNKNOWN; /** @@ -605,7 +605,7 @@ public function __getLastRequestHeaders(): ?string {} public function __getLastResponseHeaders(): ?string {} /** @tentative-return-type */ - public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false): ?string {} + public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null): ?string {} /** @tentative-return-type */ public function __setCookie(string $name, ?string $value = null): void {} diff --git a/ext/soap/soap_arginfo.h b/ext/soap/soap_arginfo.h index e932f2af71093..155348e9e98bb 100644 --- a/ext/soap/soap_arginfo.h +++ b/ext/soap/soap_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 78a27b18c6b4007494a6aed9acc5f6e99c6f0350 */ + * Stub hash: 24e266bf0933d5622f2a341db5b694ecb1740f13 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_use_soap_error_handler, 0, 0, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, enable, _IS_BOOL, 0, "true") @@ -124,6 +124,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SoapClient___doR ZEND_ARG_TYPE_INFO(0, action, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, version, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, oneWay, _IS_BOOL, 0, "false") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, uriParserClass, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SoapClient___setCookie, 0, 1, IS_VOID, 0) @@ -238,7 +239,7 @@ static void register_soap_symbols(int module_number) REGISTER_LONG_CONSTANT("SOAP_1_2", SOAP_1_2, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_SESSION", SOAP_PERSISTENCE_SESSION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_REQUEST", SOAP_PERSISTENCE_REQUEST, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SOAP_FUNCTIONS_ALL", SOAP_FUNCTIONS_ALL, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_SOAP_FUNCTIONS_ALL = REGISTER_LONG_CONSTANT("SOAP_FUNCTIONS_ALL", SOAP_FUNCTIONS_ALL, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("SOAP_ENCODED", SOAP_ENCODED, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_LITERAL", SOAP_LITERAL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_RPC", SOAP_RPC, CONST_PERSISTENT); @@ -315,6 +316,14 @@ static void register_soap_symbols(int module_number) REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv2", SOAP_SSL_METHOD_SSLv2, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv3", SOAP_SSL_METHOD_SSLv3, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv23", SOAP_SSL_METHOD_SSLv23, CONST_PERSISTENT); + + + zend_attribute *attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0 = zend_add_global_constant_attribute(const_SOAP_FUNCTIONS_ALL, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); + attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0_arg1_str = zend_string_init("as enabling all functions is a possible security concern", strlen("as enabling all functions is a possible security concern"), 1); + ZVAL_STR(&attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0->args[1].value, attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0_arg1_str); + attribute_Deprecated_const_SOAP_FUNCTIONS_ALL_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_Soap_Url(void) diff --git a/ext/soap/tests/SoapServer/__getLastResponse.phpt b/ext/soap/tests/SoapServer/__getLastResponse.phpt index 83c20d3c3a49c..900a880359731 100644 --- a/ext/soap/tests/SoapServer/__getLastResponse.phpt +++ b/ext/soap/tests/SoapServer/__getLastResponse.phpt @@ -18,7 +18,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/any.phpt b/ext/soap/tests/any.phpt index 6b08e395c2b1a..c25748997aba5 100644 --- a/ext/soap/tests/any.phpt +++ b/ext/soap/tests/any.phpt @@ -33,7 +33,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('echoAnyElement'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug28969.phpt b/ext/soap/tests/bugs/bug28969.phpt index 71de59939f8de..661e1fc82277d 100644 --- a/ext/soap/tests/bugs/bug28969.phpt +++ b/ext/soap/tests/bugs/bug28969.phpt @@ -18,7 +18,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug29795.phpt b/ext/soap/tests/bugs/bug29795.phpt index 1db3226ab171f..395d3b6c7ec61 100644 --- a/ext/soap/tests/bugs/bug29795.phpt +++ b/ext/soap/tests/bugs/bug29795.phpt @@ -12,7 +12,7 @@ class LocalSoapClient extends SoapClient { parent::__construct($wsdl, $options); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { return <<server->addFunction('EchoString'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug29844.phpt b/ext/soap/tests/bugs/bug29844.phpt index 7f5178ec6db7a..c98c3041bbb6a 100644 --- a/ext/soap/tests/bugs/bug29844.phpt +++ b/ext/soap/tests/bugs/bug29844.phpt @@ -22,7 +22,7 @@ class LocalSoapClient extends SoapClient { $this->server->setClass('hello_world'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug30045.phpt b/ext/soap/tests/bugs/bug30045.phpt index a84b73a7830f8..7dac3d0266311 100644 --- a/ext/soap/tests/bugs/bug30045.phpt +++ b/ext/soap/tests/bugs/bug30045.phpt @@ -21,7 +21,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('foo'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { $xml = simplexml_load_string($request); echo $xml->children("http://schemas.xmlsoap.org/soap/envelope/")->Body->children("http://test-uri")->children()->param1->asXML(),"\n"; unset($xml); diff --git a/ext/soap/tests/bugs/bug30106.phpt b/ext/soap/tests/bugs/bug30106.phpt index d924a5bb8b32a..0a891b4cb59dd 100644 --- a/ext/soap/tests/bugs/bug30106.phpt +++ b/ext/soap/tests/bugs/bug30106.phpt @@ -21,7 +21,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("getContinentList"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug30175.phpt b/ext/soap/tests/bugs/bug30175.phpt index ab0ab5cc11c7f..9f17f60162dd8 100644 --- a/ext/soap/tests/bugs/bug30175.phpt +++ b/ext/soap/tests/bugs/bug30175.phpt @@ -9,7 +9,7 @@ soap.wsdl_cache_enabled=0 class LocalSoapClient extends SoapClient { - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { return << server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug31695.phpt b/ext/soap/tests/bugs/bug31695.phpt index ba8a6ae000618..0d95cc6cfe67c 100644 --- a/ext/soap/tests/bugs/bug31695.phpt +++ b/ext/soap/tests/bugs/bug31695.phpt @@ -19,7 +19,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("Test"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$location\n"; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug31755.phpt b/ext/soap/tests/bugs/bug31755.phpt index cf8987db3ee13..c4b2c622b6af1 100644 --- a/ext/soap/tests/bugs/bug31755.phpt +++ b/ext/soap/tests/bugs/bug31755.phpt @@ -5,7 +5,7 @@ soap --FILE-- server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug32941.phpt b/ext/soap/tests/bugs/bug32941.phpt index 0b4ac3ab30efd..85f4434f06592 100644 --- a/ext/soap/tests/bugs/bug32941.phpt +++ b/ext/soap/tests/bugs/bug32941.phpt @@ -5,7 +5,7 @@ soap --FILE-- server->addFunction('EchoString'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug34643.phpt b/ext/soap/tests/bugs/bug34643.phpt index 5c23cbd7c7b37..27542c2c2870a 100644 --- a/ext/soap/tests/bugs/bug34643.phpt +++ b/ext/soap/tests/bugs/bug34643.phpt @@ -23,7 +23,7 @@ class LocalSoapClient extends SoapClient { $this->server->setClass('fp'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug35142.phpt b/ext/soap/tests/bugs/bug35142.phpt index 5f46bbf84113c..d596c5eb54432 100644 --- a/ext/soap/tests/bugs/bug35142.phpt +++ b/ext/soap/tests/bugs/bug35142.phpt @@ -25,7 +25,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('PostEvents'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$request\n"; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug35273.phpt b/ext/soap/tests/bugs/bug35273.phpt index 93e54626c5266..c35d545851feb 100644 --- a/ext/soap/tests/bugs/bug35273.phpt +++ b/ext/soap/tests/bugs/bug35273.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- server->addFunction('PostEvents'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$request\n"; $this->server->handle($request); return $response; diff --git a/ext/soap/tests/bugs/bug36226.phpt b/ext/soap/tests/bugs/bug36226.phpt index 38ece5d0b87a0..c1d86ce4b3d92 100644 --- a/ext/soap/tests/bugs/bug36226.phpt +++ b/ext/soap/tests/bugs/bug36226.phpt @@ -25,7 +25,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('PostEvents'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo "$request\n"; ob_start(); $this->server->handle($request); diff --git a/ext/soap/tests/bugs/bug36999.phpt b/ext/soap/tests/bugs/bug36999.phpt index 04673649da232..d4ed65621e2a0 100644 --- a/ext/soap/tests/bugs/bug36999.phpt +++ b/ext/soap/tests/bugs/bug36999.phpt @@ -20,7 +20,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('echoLong'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug37083.phpt b/ext/soap/tests/bugs/bug37083.phpt index 441b51022b8a6..8e5326e03439f 100644 --- a/ext/soap/tests/bugs/bug37083.phpt +++ b/ext/soap/tests/bugs/bug37083.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache=3 --FILE-- diff --git a/ext/soap/tests/bugs/bug38004.phpt b/ext/soap/tests/bugs/bug38004.phpt index 7953487ab1ece..3ca5aeda814f8 100644 --- a/ext/soap/tests/bugs/bug38004.phpt +++ b/ext/soap/tests/bugs/bug38004.phpt @@ -21,7 +21,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38005.phpt b/ext/soap/tests/bugs/bug38005.phpt index ca3944ebc3db3..67837861ea5eb 100644 --- a/ext/soap/tests/bugs/bug38005.phpt +++ b/ext/soap/tests/bugs/bug38005.phpt @@ -19,7 +19,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38055.phpt b/ext/soap/tests/bugs/bug38055.phpt index b066bf892e37a..ad951b537f238 100644 --- a/ext/soap/tests/bugs/bug38055.phpt +++ b/ext/soap/tests/bugs/bug38055.phpt @@ -22,7 +22,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38067.phpt b/ext/soap/tests/bugs/bug38067.phpt index 2f25a87a1cf37..962e0c29d253f 100644 --- a/ext/soap/tests/bugs/bug38067.phpt +++ b/ext/soap/tests/bugs/bug38067.phpt @@ -21,7 +21,7 @@ class TestSoapClient extends SoapClient { $this->server->addFunction('Test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = 0, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug38536.phpt b/ext/soap/tests/bugs/bug38536.phpt index 5865e6a904ab9..c64772ccbc734 100644 --- a/ext/soap/tests/bugs/bug38536.phpt +++ b/ext/soap/tests/bugs/bug38536.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/bugs/bug39815.phpt b/ext/soap/tests/bugs/bug39815.phpt index 51178e40e5b89..0eeb18cf416fb 100644 --- a/ext/soap/tests/bugs/bug39815.phpt +++ b/ext/soap/tests/bugs/bug39815.phpt @@ -23,7 +23,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug42692.phpt b/ext/soap/tests/bugs/bug42692.phpt index 5ed9254b51726..fe4840d9268de 100644 --- a/ext/soap/tests/bugs/bug42692.phpt +++ b/ext/soap/tests/bugs/bug42692.phpt @@ -19,7 +19,7 @@ class TestSoap extends SoapClient { $this->server->addFunction("checkAuth"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug43045.phpt b/ext/soap/tests/bugs/bug43045.phpt index f1e3af7765b67..79a746e1692f9 100644 --- a/ext/soap/tests/bugs/bug43045.phpt +++ b/ext/soap/tests/bugs/bug43045.phpt @@ -16,7 +16,7 @@ class TestSoapClient extends SoapClient { $this->server = new SoapServer($wsdl, $options); $this->server->addFunction('test'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug44882.phpt b/ext/soap/tests/bugs/bug44882.phpt index 73049602aaf9c..93857fd3b27ba 100644 --- a/ext/soap/tests/bugs/bug44882.phpt +++ b/ext/soap/tests/bugs/bug44882.phpt @@ -8,7 +8,7 @@ soap.wsdl_cache_enabled=0 diff --git a/ext/soap/tests/bugs/bug46419.phpt b/ext/soap/tests/bugs/bug46419.phpt index e12adfb08f20c..090f4e08a5b8a 100644 --- a/ext/soap/tests/bugs/bug46419.phpt +++ b/ext/soap/tests/bugs/bug46419.phpt @@ -17,7 +17,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('bar'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug47021.phpt b/ext/soap/tests/bugs/bug47021.phpt index af12d7c4c39c5..19b034b9eed23 100644 --- a/ext/soap/tests/bugs/bug47021.phpt +++ b/ext/soap/tests/bugs/bug47021.phpt @@ -57,9 +57,9 @@ $options = [ class BugSoapClient extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = null): string + public function __doRequest($request, $location, $action, $version, $one_way = null, ?string $uriParserClass = null): string { - $response = parent::__doRequest($request, $location, $action, $version, $one_way); + $response = parent::__doRequest($request, $location, $action, $version, $one_way, $uriParserClass); var_dump(strlen($response)); diff --git a/ext/soap/tests/bugs/bug50675.phpt b/ext/soap/tests/bugs/bug50675.phpt index e4bad4ffdfacf..bc6a47577e2b7 100644 --- a/ext/soap/tests/bugs/bug50675.phpt +++ b/ext/soap/tests/bugs/bug50675.phpt @@ -6,7 +6,7 @@ soap server->setObject(new testSoap()); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/bugs/bug54911.phpt b/ext/soap/tests/bugs/bug54911.phpt index 3247563dba496..0b1daec31345c 100644 --- a/ext/soap/tests/bugs/bug54911.phpt +++ b/ext/soap/tests/bugs/bug54911.phpt @@ -5,7 +5,7 @@ soap --FILE-- diff --git a/ext/soap/tests/bugs/bug66049.phpt b/ext/soap/tests/bugs/bug66049.phpt index e48845a8a142b..c31d0d7bcccdf 100644 --- a/ext/soap/tests/bugs/bug66049.phpt +++ b/ext/soap/tests/bugs/bug66049.phpt @@ -15,7 +15,7 @@ function soap_string_from_xml($str) } class TestSoapClient extends SoapClient { - function __doRequest($request, $location, $action, $version, $one_way = 0): ?string { + function __doRequest($request, $location, $action, $version, $one_way = 0, ?string $uriParserClass = null): ?string { $res=' diff --git a/ext/soap/tests/bugs/bug69085.phpt b/ext/soap/tests/bugs/bug69085.phpt index 3572efa5e381d..5974ce425319a 100644 --- a/ext/soap/tests/bugs/bug69085.phpt +++ b/ext/soap/tests/bugs/bug69085.phpt @@ -9,7 +9,7 @@ soap.wsdl_cache_enabled=0 #[AllowDynamicProperties] class MySoapClient extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request, "\n"; return ''; } diff --git a/ext/soap/tests/bugs/bug69668.phpt b/ext/soap/tests/bugs/bug69668.phpt index b93163c164de1..75fe05d5c2ed1 100644 --- a/ext/soap/tests/bugs/bug69668.phpt +++ b/ext/soap/tests/bugs/bug69668.phpt @@ -5,7 +5,7 @@ soap --FILE-- '', 'uri' => 'http://example.org']) extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request; return ''; } diff --git a/ext/soap/tests/bugs/bug71996.phpt b/ext/soap/tests/bugs/bug71996.phpt index a6b2a71765b54..d78661ad3273e 100644 --- a/ext/soap/tests/bugs/bug71996.phpt +++ b/ext/soap/tests/bugs/bug71996.phpt @@ -6,7 +6,7 @@ soap '', 'uri' => 'http://example.org']) extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request, "\n"; return ''; } diff --git a/ext/soap/tests/bugs/bug73237.phpt b/ext/soap/tests/bugs/bug73237.phpt index 643c99a8c22a3..32ee055706354 100644 --- a/ext/soap/tests/bugs/bug73237.phpt +++ b/ext/soap/tests/bugs/bug73237.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- trueCampaignMember00vi0000011VMgeAAG00vi0000011VMgeAAG701i0000001lreeAAASent00Qi000001UrbYFEAZLeadangela.lansbury@cbs.com1 EOF; diff --git a/ext/soap/tests/bugs/bug77141.phpt b/ext/soap/tests/bugs/bug77141.phpt index 4a86b6af902b4..67b07d598650a 100644 --- a/ext/soap/tests/bugs/bug77141.phpt +++ b/ext/soap/tests/bugs/bug77141.phpt @@ -5,7 +5,7 @@ soap --FILE-- WSDL_CACHE_NONE, 'trace' => 1, ]) extends SoapClient { - public function __doRequest($request, $location, $action, $version, $one_way = 0): string { + public function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { echo $request, "\n"; return ''; } diff --git a/ext/soap/tests/bugs/gh18640.phpt b/ext/soap/tests/bugs/gh18640.phpt new file mode 100644 index 0000000000000..4e76d699b3266 --- /dev/null +++ b/ext/soap/tests/bugs/gh18640.phpt @@ -0,0 +1,42 @@ +--TEST--- +GH-18640 (heap-use-after-free ext/soap/php_encoding.c:299:32 in soap_check_zval_ref) +--EXTENSIONS-- +soap +--CREDITS-- +YuanchengJiang +--FILE-- + 1, 'classmap' => ['logOnEvent' => 'LogOnEvent', 'events' => 'IVREvents']]); +$timestamp = new LogOnEvent(); // Bogus! +$logOffEvents[] = new LogOffEvent($timestamp); +$logOffEvents[] = new LogOffEvent($timestamp); +$ivrEvents = new IVREvents($logOffEvents); +$result = $soapClient->PostEvents($ivrEvents); + +class LogOffEvent { + function __construct(public $timestamp) { + $this->timestamp = $timestamp; + } +} + +class LogOnEvent { +} + +class IVREvents { + function __construct(public $logOffEvent) { + } +} +?> +--EXPECT-- +string(359) " + +" diff --git a/ext/soap/tests/bugs/gh18990.phpt b/ext/soap/tests/bugs/gh18990.phpt new file mode 100644 index 0000000000000..30dbc0fe8b751 --- /dev/null +++ b/ext/soap/tests/bugs/gh18990.phpt @@ -0,0 +1,58 @@ +--TEST-- +GH-18990 (SOAP HTTP socket not closing on object destruction) +--INI-- +soap.wsdl_cache_enabled=0 +--EXTENSIONS-- +soap +--SKIPIF-- + +text0text1text2text3text4text5text6text7text8text9 +EOF; + +$responses = [ + "data://text/plain,HTTP/1.1 200 OK\r\n". + "Content-Type: text/xml;charset=utf-8\r\n". + "Connection: Keep-Alive\r\n". + "Content-Length: ".strlen($wsdl)."\r\n". + "\r\n". + $wsdl, + + "data://text/plain,HTTP/1.1 200 OK\r\n". + "Content-Type: text/xml;charset=utf-8\r\n". + "Connection: Keep-Alive\r\n". + "Content-Length: ".strlen($soap)."\r\n". + "\r\n". + $soap, +]; + +['pid' => $pid, 'uri' => $uri] = http_server($responses); + +$options = [ + 'trace' => false, + 'location' => $uri, +]; + +$cnt = count(get_resources()); + +$client = new SoapClient($uri, $options); + +var_dump(count($client->getItems())); + +http_server_kill($pid); + +unset($client); +var_dump(count(get_resources()) - $cnt); +?> +--EXPECT-- +int(10) +int(0) diff --git a/ext/soap/tests/bugs/gh19784.phpt b/ext/soap/tests/bugs/gh19784.phpt new file mode 100644 index 0000000000000..1f718e74c4598 --- /dev/null +++ b/ext/soap/tests/bugs/gh19784.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-19784 (SoapServer memory leak) +--EXTENSIONS-- +soap +--FILE-- + $v_5257); +new SoapServer('foobarbaz',$v_5238,); +?> +--EXPECTF-- + +%s%a diff --git a/ext/soap/tests/bugs/segfault_assertion_props.phpt b/ext/soap/tests/bugs/segfault_assertion_props.phpt index 75cefa57642e0..f11ea61f7cd3f 100644 --- a/ext/soap/tests/bugs/segfault_assertion_props.phpt +++ b/ext/soap/tests/bugs/segfault_assertion_props.phpt @@ -7,7 +7,7 @@ soap --FILE-- diff --git a/ext/soap/tests/classmap002.phpt b/ext/soap/tests/classmap002.phpt index 626b9f8ff66b5..13c82c1b53838 100644 --- a/ext/soap/tests/classmap002.phpt +++ b/ext/soap/tests/classmap002.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/classmap003.phpt b/ext/soap/tests/classmap003.phpt index 322445fa16af6..31839f841f8f3 100644 --- a/ext/soap/tests/classmap003.phpt +++ b/ext/soap/tests/classmap003.phpt @@ -34,7 +34,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/classmap004.phpt b/ext/soap/tests/classmap004.phpt index 1fbf4c6ccad3d..172a6db7b4483 100644 --- a/ext/soap/tests/classmap004.phpt +++ b/ext/soap/tests/classmap004.phpt @@ -42,7 +42,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/classmap005.phpt b/ext/soap/tests/classmap005.phpt index ce4aa2b66bb85..a39adfa85033a 100644 --- a/ext/soap/tests/classmap005.phpt +++ b/ext/soap/tests/classmap005.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/classmap006.phpt b/ext/soap/tests/classmap006.phpt index 817a3a883c7eb..c56f876148a1c 100644 --- a/ext/soap/tests/classmap006.phpt +++ b/ext/soap/tests/classmap006.phpt @@ -39,7 +39,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/classmap007.phpt b/ext/soap/tests/classmap007.phpt index b6fe394eaeecb..9a59e647bc96e 100644 --- a/ext/soap/tests/classmap007.phpt +++ b/ext/soap/tests/classmap007.phpt @@ -39,7 +39,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction("f"); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/gh15711.phpt b/ext/soap/tests/gh15711.phpt index b72251cc6f95b..17ff051698fdb 100644 --- a/ext/soap/tests/gh15711.phpt +++ b/ext/soap/tests/gh15711.phpt @@ -28,7 +28,7 @@ enum NonBackedEnum } class TestSoapClient extends SoapClient { - function __doRequest($request, $location, $action, $version, $one_way = 0): ?string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): ?string { echo $request; } } diff --git a/ext/soap/tests/gh16318.phpt b/ext/soap/tests/gh16318.phpt index a0a4c925df051..0c38b6fc8de30 100644 --- a/ext/soap/tests/gh16318.phpt +++ b/ext/soap/tests/gh16318.phpt @@ -15,7 +15,7 @@ $test2["a"] = "a"; $test2[] =& $test2; class TestSoapClient extends SoapClient { - public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false): ?string + public function __doRequest(string $request, string $location, string $action, int $version, bool $oneWay = false, ?string $uriParserClass = null): ?string { die($request); } diff --git a/ext/soap/tests/server003.phpt b/ext/soap/tests/server003.phpt index 1425daf819404..c278ca23a1959 100644 --- a/ext/soap/tests/server003.phpt +++ b/ext/soap/tests/server003.phpt @@ -27,7 +27,7 @@ $server->handle($HTTP_RAW_POST_DATA); echo "ok\n"; ?> --EXPECTF-- -Deprecated: Constant SOAP_FUNCTIONS_ALL is deprecated in %s on line %d +Deprecated: Constant SOAP_FUNCTIONS_ALL is deprecated since 8.4, as enabling all functions is a possible security concern in %s on line %d Deprecated: SoapServer::addFunction(): Enabling all functions via SOAP_FUNCTIONS_ALL is deprecated since 8.4, due to possible security concerns. If all PHP functions should be enabled, the flattened return value of get_defined_functions() can be used in %s on line %d diff --git a/ext/soap/tests/soap_qname_crash.phpt b/ext/soap/tests/soap_qname_crash.phpt new file mode 100644 index 0000000000000..53d6904db1c95 --- /dev/null +++ b/ext/soap/tests/soap_qname_crash.phpt @@ -0,0 +1,49 @@ +--TEST-- +Test SoapClient with excessively large QName prefix in SoapVar +--EXTENSIONS-- +soap +--SKIPIF-- + +--INI-- +memory_limit=6144M +--FILE-- + 'http://127.0.0.1/', + 'uri' => 'urn:dummy', + 'trace' => 1, + 'exceptions' => true, +]; +$client = new TestSoapClient(null, $options); +$client->__soapCall("DummyFunction", [$var]); +?> +--EXPECT-- +Attempting to create SoapVar with very large QName +Attempting encoding + +value diff --git a/ext/soap/tests/transport001.phpt b/ext/soap/tests/transport001.phpt index 297d0e1288e7e..c735b2e139d76 100644 --- a/ext/soap/tests/transport001.phpt +++ b/ext/soap/tests/transport001.phpt @@ -17,7 +17,7 @@ class LocalSoapClient extends SoapClient { $this->server->addFunction('Add'); } - function __doRequest($request, $location, $action, $version, $one_way = 0): string { + function __doRequest($request, $location, $action, $version, $one_way = false, ?string $uriParserClass = null): string { ob_start(); $this->server->handle($request); $response = ob_get_contents(); diff --git a/ext/soap/tests/typemap003.phpt b/ext/soap/tests/typemap003.phpt index a7b83b6348bba..3f4960f8d5d6b 100644 --- a/ext/soap/tests/typemap003.phpt +++ b/ext/soap/tests/typemap003.phpt @@ -8,7 +8,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/typemap004.phpt b/ext/soap/tests/typemap004.phpt index 61b62867205fc..c0feb6b4ebbc8 100644 --- a/ext/soap/tests/typemap004.phpt +++ b/ext/soap/tests/typemap004.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/typemap008.phpt b/ext/soap/tests/typemap008.phpt index 8abd8039f8d59..7e7012b6ad5ca 100644 --- a/ext/soap/tests/typemap008.phpt +++ b/ext/soap/tests/typemap008.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/typemap012.phpt b/ext/soap/tests/typemap012.phpt index e31d3ffa0ac48..13bb0c8984796 100644 --- a/ext/soap/tests/typemap012.phpt +++ b/ext/soap/tests/typemap012.phpt @@ -7,7 +7,7 @@ soap.wsdl_cache_enabled=0 --FILE-- blocking) { + flags |= SOCK_NONBLOCK; + } + + out_sock->bsd_socket = accept4(in_sock->bsd_socket, la, la_len, flags); + + if (IS_INVALID_SOCKET(out_sock)) { + PHP_SOCKET_ERROR(out_sock, "unable to accept incoming connection", errno); + return 0; + } +#else out_sock->bsd_socket = accept(in_sock->bsd_socket, la, la_len); if (IS_INVALID_SOCKET(out_sock)) { @@ -292,7 +307,7 @@ static bool php_accept_connect(php_socket *in_sock, php_socket *out_sock, struct #if !defined(PHP_WIN32) /** - * accept4 could had been used but not all platforms support it (e.g. Haiku, solaris < 11.4, ...) + * for fewer and fewer platforms not supporting accept4 syscall we use fcntl instead, * win32, not having any concept of child process, has no need to address it. */ int mode; @@ -310,6 +325,7 @@ static bool php_accept_connect(php_socket *in_sock, php_socket *out_sock, struct return 0; } } +#endif #endif out_sock->error = 0; @@ -2571,7 +2587,7 @@ PHP_FUNCTION(socket_import_stream) ZEND_PARSE_PARAMETERS_END(); php_stream_from_zval(stream, zstream); - if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void**)&socket, 1)) { + if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void**)&socket, 1) == FAILURE) { /* error supposedly already shown */ RETURN_FALSE; } @@ -2774,8 +2790,16 @@ PHP_FUNCTION(socket_addrinfo_lookup) zend_argument_type_error(3, "\"ai_family\" key must be of type int, %s given", zend_zval_type_name(hint)); RETURN_THROWS(); } - if (val < 0 || val >= AF_MAX) { - zend_argument_value_error(3, "\"ai_family\" key must be between 0 and %d", AF_MAX - 1); + // Some platforms support also PF_LOCAL/AF_UNIX (e.g. FreeBSD) but the security concerns implied + // make it not worth handling it (e.g. unwarranted write permissions on the socket). + // Note existing socket_addrinfo* api already forbid such case. +#ifdef HAVE_IPV6 + if (val != AF_INET && val != AF_INET6) { + zend_argument_value_error(3, "\"ai_family\" key must be AF_INET or AF_INET6"); +#else + if (val != AF_INET) { + zend_argument_value_error(3, "\"ai_family\" key must be AF_INET"); +#endif RETURN_THROWS(); } hints.ai_family = (int)val; @@ -2827,7 +2851,6 @@ PHP_FUNCTION(socket_addrinfo_lookup) PHP_FUNCTION(socket_addrinfo_bind) { zval *arg1; - int retval; php_addrinfo *ai; php_socket *php_sock; @@ -2837,6 +2860,8 @@ PHP_FUNCTION(socket_addrinfo_bind) ai = Z_ADDRESS_INFO_P(arg1); + ZEND_ASSERT(ai->addrinfo.ai_family == AF_INET || ai->addrinfo.ai_family == AF_INET6); + PHP_ETH_PROTO_CHECK(ai->addrinfo.ai_protocol, ai->addrinfo.ai_family); object_init_ex(return_value, socket_ce); @@ -2855,31 +2880,7 @@ PHP_FUNCTION(socket_addrinfo_bind) php_sock->error = 0; php_sock->blocking = 1; - switch(php_sock->type) { - case AF_UNIX: - { - // AF_UNIX sockets via getaddrino are not implemented due to security problems - close(php_sock->bsd_socket); - zval_ptr_dtor(return_value); - RETURN_FALSE; - } - - case AF_INET: -#ifdef HAVE_IPV6 - case AF_INET6: -#endif - { - retval = bind(php_sock->bsd_socket, ai->addrinfo.ai_addr, ai->addrinfo.ai_addrlen); - break; - } - default: - close(php_sock->bsd_socket); - zval_ptr_dtor(return_value); - zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, or AF_INET6"); - RETURN_THROWS(); - } - - if (retval != 0) { + if (bind(php_sock->bsd_socket, ai->addrinfo.ai_addr, ai->addrinfo.ai_addrlen) != 0) { PHP_SOCKET_ERROR(php_sock, "Unable to bind address", errno); close(php_sock->bsd_socket); zval_ptr_dtor(return_value); @@ -2892,7 +2893,6 @@ PHP_FUNCTION(socket_addrinfo_bind) PHP_FUNCTION(socket_addrinfo_connect) { zval *arg1; - int retval; php_addrinfo *ai; php_socket *php_sock; @@ -2902,6 +2902,8 @@ PHP_FUNCTION(socket_addrinfo_connect) ai = Z_ADDRESS_INFO_P(arg1); + ZEND_ASSERT(ai->addrinfo.ai_family == AF_INET || ai->addrinfo.ai_family == AF_INET6); + PHP_ETH_PROTO_CHECK(ai->addrinfo.ai_protocol, ai->addrinfo.ai_family); object_init_ex(return_value, socket_ce); @@ -2920,31 +2922,7 @@ PHP_FUNCTION(socket_addrinfo_connect) php_sock->error = 0; php_sock->blocking = 1; - switch(php_sock->type) { - case AF_UNIX: - { - // AF_UNIX sockets via getaddrino are not implemented due to security problems - close(php_sock->bsd_socket); - zval_ptr_dtor(return_value); - RETURN_FALSE; - } - - case AF_INET: -#ifdef HAVE_IPV6 - case AF_INET6: -#endif - { - retval = connect(php_sock->bsd_socket, ai->addrinfo.ai_addr, ai->addrinfo.ai_addrlen); - break; - } - default: - zend_argument_value_error(1, "socket type must be one of AF_UNIX, AF_INET, or AF_INET6"); - close(php_sock->bsd_socket); - zval_ptr_dtor(return_value); - RETURN_THROWS(); - } - - if (retval != 0) { + if (connect(php_sock->bsd_socket, ai->addrinfo.ai_addr, ai->addrinfo.ai_addrlen) != 0) { PHP_SOCKET_ERROR(php_sock, "Unable to connect address", errno); close(php_sock->bsd_socket); zval_ptr_dtor(return_value); diff --git a/ext/sockets/tests/mcast_sockettype_error.phpt b/ext/sockets/tests/mcast_sockettype_error.phpt new file mode 100644 index 0000000000000..56308534ebc4d --- /dev/null +++ b/ext/sockets/tests/mcast_sockettype_error.phpt @@ -0,0 +1,30 @@ +--TEST-- +Multicast attempt on unsupported socket type +--EXTENSIONS-- +sockets +--SKIPIF-- + +--FILE-- + '127.0.0.1', + "interface" => "lo", + )); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +?> +--EXPECT-- +IP address used in the context of an unexpected type of socket diff --git a/ext/sockets/tests/socket_export_stream-5.phpt b/ext/sockets/tests/socket_export_stream-5.phpt deleted file mode 100644 index ffad1935b64be..0000000000000 --- a/ext/sockets/tests/socket_export_stream-5.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -socket_export_stream: effects of leaked handles ---EXTENSIONS-- -sockets -zend_test ---INI-- -report_memleaks=0 ---FILE-- - ---EXPECT-- -Done. diff --git a/ext/sockets/tests/socket_getaddrinfo_error.phpt b/ext/sockets/tests/socket_getaddrinfo_error.phpt index c3488b540c69b..a2455821e70e2 100644 --- a/ext/sockets/tests/socket_getaddrinfo_error.phpt +++ b/ext/sockets/tests/socket_getaddrinfo_error.phpt @@ -110,7 +110,7 @@ socket_addrinfo_lookup(): Argument #3 ($hints) "ai_family" key must be of type i socket_addrinfo_lookup(): Argument #3 ($hints) "ai_socktype" key must be of type int, stdClass given socket_addrinfo_lookup(): Argument #3 ($hints) "ai_flags" key must be of type int, stdClass given socket_addrinfo_lookup(): Argument #3 ($hints) "ai_protocol" key must be of type int, stdClass given -socket_addrinfo_lookup(): Argument #3 ($hints) "ai_family" key must be between 0 and %d +socket_addrinfo_lookup(): Argument #3 ($hints) "ai_family" key must be AF_INET%A socket_addrinfo_lookup(): Argument #3 ($hints) "ai_socktype" key must be between 0 and %d socket_addrinfo_lookup(): Argument #3 ($hints) "ai_flags" key must be between 0 and %d socket_addrinfo_lookup(): Argument #3 ($hints) "ai_protocol" key must be between 0 and %d diff --git a/ext/sockets/tests/socket_import_stream-5.phpt b/ext/sockets/tests/socket_import_stream-5.phpt deleted file mode 100644 index 9a684d054ba0e..0000000000000 --- a/ext/sockets/tests/socket_import_stream-5.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -socket_import_stream: effects of leaked handles ---EXTENSIONS-- -sockets -zend_test ---INI-- -report_memleaks=0 ---FILE-- - ---EXPECT-- -Done. diff --git a/ext/sodium/config.m4 b/ext/sodium/config.m4 index 40da5e5bf2d14..178568d72aeba 100644 --- a/ext/sodium/config.m4 +++ b/ext/sodium/config.m4 @@ -19,8 +19,7 @@ if test "$PHP_SODIUM" != "no"; then AS_IF([test "$ac_cv_sizeof_long" -eq 4], [ SODIUM_COMPILER_FLAGS="$SODIUM_COMPILER_FLAGS -Wno-type-limits" AX_CHECK_COMPILE_FLAG([-Wno-logical-op], - [SODIUM_COMPILER_FLAGS="$SODIUM_COMPILER_FLAGS -Wno-logical-op"],, - [-Werror]) + [SODIUM_COMPILER_FLAGS="$SODIUM_COMPILER_FLAGS -Wno-logical-op"]) ]) PHP_NEW_EXTENSION([sodium], diff --git a/ext/sodium/sodium_pwhash.stub.php b/ext/sodium/sodium_pwhash.stub.php index 58d7139c0ebc3..82c04bfa4b1a1 100644 --- a/ext/sodium/sodium_pwhash.stub.php +++ b/ext/sodium/sodium_pwhash.stub.php @@ -3,13 +3,7 @@ /** @generate-class-entries */ #if SODIUM_LIBRARY_VERSION_MAJOR > 9 || (SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR >= 6) -/** - * @var string - */ const PASSWORD_ARGON2I = "argon2i"; -/** - * @var string - */ const PASSWORD_ARGON2ID = "argon2id"; /** * @var int @@ -26,8 +20,5 @@ * @cvalue PHP_SODIUM_PWHASH_THREADS */ const PASSWORD_ARGON2_DEFAULT_THREADS = UNKNOWN; -/** - * @var string - */ const PASSWORD_ARGON2_PROVIDER = "sodium"; #endif diff --git a/ext/sodium/sodium_pwhash_arginfo.h b/ext/sodium/sodium_pwhash_arginfo.h index 465f3090191d1..d559a74fbc1fe 100644 --- a/ext/sodium/sodium_pwhash_arginfo.h +++ b/ext/sodium/sodium_pwhash_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: dd94e709f115ce05df0e25a8cb48c62438bb6d01 */ + * Stub hash: d1e804ceea5e18fc5a4eca50b318d98387b2a470 */ static void register_sodium_pwhash_symbols(int module_number) { diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 1149be29bd46e..f796b936daeec 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -213,7 +213,7 @@ PHP_FUNCTION(class_uses) SPL_ADD_CLASS(UnderflowException, z_list, sub, allow, ce_flags); \ SPL_ADD_CLASS(UnexpectedValueException, z_list, sub, allow, ce_flags); \ -/* {{{ Return an array containing the names of all clsses and interfaces defined in SPL */ +/* {{{ Return an array containing the names of all classes and interfaces defined in SPL */ PHP_FUNCTION(spl_classes) { if (zend_parse_parameters_none() == FAILURE) { @@ -582,6 +582,13 @@ PHP_FUNCTION(spl_autoload_unregister) if (fcc.function_handler && zend_string_equals_literal( fcc.function_handler->common.function_name, "spl_autoload_call")) { + php_error_docref(NULL, E_DEPRECATED, + "Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated," + " to remove all registered autoloaders, call spl_autoload_unregister()" + " for all values returned from spl_autoload_functions()"); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } if (spl_autoload_functions) { /* Don't destroy the hash table, as we might be iterating over it right now. */ zend_hash_clean(spl_autoload_functions); diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index b950330061920..ea21b422229b3 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -280,6 +280,7 @@ static zend_result get_hash_key(spl_hash_key *key, spl_array_object *intern, zva try_again: switch (Z_TYPE_P(offset)) { case IS_NULL: + zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead"); key->key = ZSTR_EMPTY_ALLOC(); return SUCCESS; case IS_STRING: @@ -984,6 +985,12 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar } } } else { + php_error_docref(NULL, E_DEPRECATED, + "Using an object as a backing array for %s is deprecated, as it allows violating class constraints and invariants", + instanceof_function(Z_OBJCE_P(object), spl_ce_ArrayIterator) ? "ArrayIterator" : "ArrayObject"); + if (UNEXPECTED(EG(exception))) { + return; + } if (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject) { ZVAL_COPY_VALUE(&garbage, &intern->array); if (just_array) { @@ -1203,43 +1210,54 @@ PHP_METHOD(ArrayObject, count) RETURN_LONG(spl_array_object_count_elements_helper(intern)); } /* }}} */ -static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, size_t fname_len, int use_arg) /* {{{ */ +enum spl_array_object_sort_methods { + SPL_NAT_SORT, + SPL_CALLBACK_SORT, + SPL_OPTIONAL_FLAG_SORT +}; + +static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, const char *fname, size_t fname_len, enum spl_array_object_sort_methods use_arg) /* {{{ */ { spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS); HashTable **ht_ptr = spl_array_get_hash_table_ptr(intern); HashTable *aht = *ht_ptr; - zval function_name, params[2], *arg = NULL; + zval params[2], *arg = NULL; - ZVAL_STRINGL(&function_name, fname, fname_len); + zend_function *fn = zend_hash_str_find_ptr(EG(function_table), fname, fname_len); + if (UNEXPECTED(fn == NULL)) { + zend_throw_error(NULL, "Cannot call method %s when function %s is disabled", fname, fname); + RETURN_THROWS(); + } ZVAL_NEW_EMPTY_REF(¶ms[0]); ZVAL_ARR(Z_REFVAL(params[0]), aht); GC_ADDREF(aht); - if (!use_arg) { + if (use_arg == SPL_NAT_SORT) { if (zend_parse_parameters_none() == FAILURE) { goto exit; } intern->nApplyCount++; - call_user_function(EG(function_table), NULL, &function_name, return_value, 1, params); + zend_call_known_function(fn, NULL, NULL, return_value, 1, params, NULL); intern->nApplyCount--; - } else if (use_arg == SPL_ARRAY_METHOD_SORT_FLAGS_ARG) { + } else if (use_arg == SPL_OPTIONAL_FLAG_SORT) { zend_long sort_flags = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &sort_flags) == FAILURE) { goto exit; } ZVAL_LONG(¶ms[1], sort_flags); intern->nApplyCount++; - call_user_function(EG(function_table), NULL, &function_name, return_value, 2, params); + zend_call_known_function(fn, NULL, NULL, return_value, 2, params, NULL); intern->nApplyCount--; } else { + ZEND_ASSERT(use_arg == SPL_CALLBACK_SORT); if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &arg) == FAILURE) { goto exit; } ZVAL_COPY_VALUE(¶ms[1], arg); intern->nApplyCount++; - call_user_function(EG(function_table), NULL, &function_name, return_value, 2, params); + zend_call_known_function(fn, NULL, NULL, return_value, 2, params, NULL); intern->nApplyCount--; } @@ -1251,7 +1269,6 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, size_t f *ht_ptr = Z_ARRVAL_P(ht_zv); ZVAL_NULL(ht_zv); zval_ptr_dtor(¶ms[0]); - zend_string_free(Z_STR(function_name)); } } /* }}} */ @@ -1261,23 +1278,23 @@ PHP_METHOD(cname, fname) \ spl_array_method(INTERNAL_FUNCTION_PARAM_PASSTHRU, #fname, sizeof(#fname)-1, use_arg); \ } -/* {{{ Sort the entries by values. */ -SPL_ARRAY_METHOD(ArrayObject, asort, SPL_ARRAY_METHOD_SORT_FLAGS_ARG) /* }}} */ +/* Sort the entries by values. */ +SPL_ARRAY_METHOD(ArrayObject, asort, SPL_OPTIONAL_FLAG_SORT) -/* {{{ Sort the entries by key. */ -SPL_ARRAY_METHOD(ArrayObject, ksort, SPL_ARRAY_METHOD_SORT_FLAGS_ARG) /* }}} */ +/* Sort the entries by key. */ +SPL_ARRAY_METHOD(ArrayObject, ksort, SPL_OPTIONAL_FLAG_SORT) -/* {{{ Sort the entries by values user defined function. */ -SPL_ARRAY_METHOD(ArrayObject, uasort, SPL_ARRAY_METHOD_CALLBACK_ARG) /* }}} */ +/* Sort the entries by values user defined function. */ +SPL_ARRAY_METHOD(ArrayObject, uasort, SPL_CALLBACK_SORT) -/* {{{ Sort the entries by key using user defined function. */ -SPL_ARRAY_METHOD(ArrayObject, uksort, SPL_ARRAY_METHOD_CALLBACK_ARG) /* }}} */ +/* Sort the entries by key using user defined function. */ +SPL_ARRAY_METHOD(ArrayObject, uksort, SPL_CALLBACK_SORT) -/* {{{ Sort the entries by values using "natural order" algorithm. */ -SPL_ARRAY_METHOD(ArrayObject, natsort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */ +/* Sort the entries by values using "natural order" algorithm. */ +SPL_ARRAY_METHOD(ArrayObject, natsort, SPL_NAT_SORT) -/* {{{ Sort the entries by key using case insensitive "natural order" algorithm. */ -SPL_ARRAY_METHOD(ArrayObject, natcasesort, SPL_ARRAY_METHOD_NO_ARG) /* }}} */ +/* {{{ Sort the entries by key using case-insensitive "natural order" algorithm. */ +SPL_ARRAY_METHOD(ArrayObject, natcasesort, SPL_NAT_SORT) /* {{{ Serialize the object */ PHP_METHOD(ArrayObject, serialize) diff --git a/ext/spl/spl_array.h b/ext/spl/spl_array.h index f3577f4beeaad..86de7a955c5b2 100644 --- a/ext/spl/spl_array.h +++ b/ext/spl/spl_array.h @@ -27,10 +27,6 @@ #define SPL_ARRAY_INT_MASK 0xFFFF0000 #define SPL_ARRAY_CLONE_MASK 0x0100FFFF -#define SPL_ARRAY_METHOD_NO_ARG 0 -#define SPL_ARRAY_METHOD_CALLBACK_ARG 1 -#define SPL_ARRAY_METHOD_SORT_FLAGS_ARG 2 - extern PHPAPI zend_class_entry *spl_ce_ArrayObject; extern PHPAPI zend_class_entry *spl_ce_ArrayIterator; extern PHPAPI zend_class_entry *spl_ce_RecursiveArrayIterator; diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 8c59e9624a332..049d850d12fc7 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -260,19 +260,16 @@ static zend_result spl_filesystem_object_get_file_name(spl_filesystem_object *in return SUCCESS; } /* }}} */ -/* TODO Make void or have callers check return value */ -static bool spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */ +static void spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */ { if (intern->file_name) { /* invalidate */ zend_string_release(intern->file_name); intern->file_name = NULL; } + if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) { intern->u.dir.entry.d_name[0] = '\0'; - return 0; - } else { - return 1; } } /* }}} */ diff --git a/ext/spl/spl_directory_arginfo.h b/ext/spl/spl_directory_arginfo.h index 55606b1a15397..434abefef4c68 100644 --- a/ext/spl/spl_directory_arginfo.h +++ b/ext/spl/spl_directory_arginfo.h @@ -482,10 +482,7 @@ static zend_class_entry *register_class_SplFileInfo(zend_class_entry *class_entr zend_attribute *attribute_Deprecated_func__bad_state_ex_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "_bad_state_ex", sizeof("_bad_state_ex") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func__bad_state_ex_0_arg0; - zend_string *attribute_Deprecated_func__bad_state_ex_0_arg0_str = zend_string_init("8.2", strlen("8.2"), 1); - ZVAL_STR(&attribute_Deprecated_func__bad_state_ex_0_arg0, attribute_Deprecated_func__bad_state_ex_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func__bad_state_ex_0->args[0].value, &attribute_Deprecated_func__bad_state_ex_0_arg0); + ZVAL_STR(&attribute_Deprecated_func__bad_state_ex_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_2)); attribute_Deprecated_func__bad_state_ex_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); return class_entry; diff --git a/ext/spl/spl_fixedarray_arginfo.h b/ext/spl/spl_fixedarray_arginfo.h index c2ff9a77ac40f..d3d84deabe6ec 100644 --- a/ext/spl/spl_fixedarray_arginfo.h +++ b/ext/spl/spl_fixedarray_arginfo.h @@ -98,15 +98,10 @@ static zend_class_entry *register_class_SplFixedArray(zend_class_entry *class_en zend_attribute *attribute_Deprecated_func___wakeup_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "__wakeup", sizeof("__wakeup") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func___wakeup_0_arg0; - zend_string *attribute_Deprecated_func___wakeup_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func___wakeup_0_arg0, attribute_Deprecated_func___wakeup_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func___wakeup_0->args[0].value, &attribute_Deprecated_func___wakeup_0_arg0); + ZVAL_STR(&attribute_Deprecated_func___wakeup_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func___wakeup_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func___wakeup_0_arg1; zend_string *attribute_Deprecated_func___wakeup_0_arg1_str = zend_string_init("this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()", strlen("this method is obsolete, as serialization hooks are provided by __unserialize() and __serialize()"), 1); - ZVAL_STR(&attribute_Deprecated_func___wakeup_0_arg1, attribute_Deprecated_func___wakeup_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func___wakeup_0->args[1].value, &attribute_Deprecated_func___wakeup_0_arg1); + ZVAL_STR(&attribute_Deprecated_func___wakeup_0->args[1].value, attribute_Deprecated_func___wakeup_0_arg1_str); attribute_Deprecated_func___wakeup_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); return class_entry; diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index d4450da42009c..628e24ac24723 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -50,7 +50,7 @@ typedef struct _spl_ptr_heap { spl_ptr_heap_ctor_func ctor; spl_ptr_heap_dtor_func dtor; spl_ptr_heap_cmp_func cmp; - int count; + size_t count; int flags; size_t max_size; size_t elem_size; @@ -267,8 +267,6 @@ static spl_ptr_heap *spl_ptr_heap_init(spl_ptr_heap_cmp_func cmp, spl_ptr_heap_c /* }}} */ static void spl_ptr_heap_insert(spl_ptr_heap *heap, void *elem, void *cmp_userdata) { /* {{{ */ - int i; - if (heap->count+1 > heap->max_size) { size_t alloc_size = heap->max_size * heap->elem_size; /* we need to allocate more memory */ @@ -280,8 +278,9 @@ static void spl_ptr_heap_insert(spl_ptr_heap *heap, void *elem, void *cmp_userda heap->flags |= SPL_HEAP_WRITE_LOCKED; /* sifting up */ - for (i = heap->count; i > 0 && heap->cmp(spl_heap_elem(heap, (i-1)/2), elem, cmp_userdata) < 0; i = (i-1)/2) { - spl_heap_elem_copy(heap, spl_heap_elem(heap, i), spl_heap_elem(heap, (i-1)/2)); + size_t pos; + for (pos = heap->count; pos > 0 && heap->cmp(spl_heap_elem(heap, (pos-1)/2), elem, cmp_userdata) < 0; pos = (pos-1)/2) { + spl_heap_elem_copy(heap, spl_heap_elem(heap, pos), spl_heap_elem(heap, (pos-1)/2)); } heap->count++; @@ -292,7 +291,7 @@ static void spl_ptr_heap_insert(spl_ptr_heap *heap, void *elem, void *cmp_userda heap->flags |= SPL_HEAP_CORRUPTED; } - spl_heap_elem_copy(heap, spl_heap_elem(heap, i), elem); + spl_heap_elem_copy(heap, spl_heap_elem(heap, pos), elem); } /* }}} */ @@ -306,8 +305,7 @@ static void *spl_ptr_heap_top(spl_ptr_heap *heap) { /* {{{ */ /* }}} */ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void *cmp_userdata) { /* {{{ */ - int i, j; - const int limit = (heap->count-1)/2; + const size_t limit = (heap->count-1)/2; void *bottom; if (heap->count == 0) { @@ -324,16 +322,17 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void bottom = spl_heap_elem(heap, --heap->count); - for (i = 0; i < limit; i = j) { + size_t parent_idx, child_idx; + for (parent_idx = 0; parent_idx < limit; parent_idx = child_idx) { /* Find smaller child */ - j = i * 2 + 1; - if (j != heap->count && heap->cmp(spl_heap_elem(heap, j+1), spl_heap_elem(heap, j), cmp_userdata) > 0) { - j++; /* next child is bigger */ + child_idx = parent_idx * 2 + 1; + if (child_idx != heap->count && heap->cmp(spl_heap_elem(heap, child_idx+1), spl_heap_elem(heap, child_idx), cmp_userdata) > 0) { + child_idx++; /* next child is bigger */ } /* swap elements between two levels */ - if(heap->cmp(bottom, spl_heap_elem(heap, j), cmp_userdata) < 0) { - spl_heap_elem_copy(heap, spl_heap_elem(heap, i), spl_heap_elem(heap, j)); + if(heap->cmp(bottom, spl_heap_elem(heap, child_idx), cmp_userdata) < 0) { + spl_heap_elem_copy(heap, spl_heap_elem(heap, parent_idx), spl_heap_elem(heap, child_idx)); } else { break; } @@ -346,7 +345,7 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void heap->flags |= SPL_HEAP_CORRUPTED; } - void *to = spl_heap_elem(heap, i); + void *to = spl_heap_elem(heap, parent_idx); if (to != bottom) { spl_heap_elem_copy(heap, to, bottom); } @@ -355,8 +354,6 @@ static zend_result spl_ptr_heap_delete_top(spl_ptr_heap *heap, void *elem, void /* }}} */ static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from) { /* {{{ */ - int i; - spl_ptr_heap *heap = emalloc(sizeof(spl_ptr_heap)); heap->dtor = from->dtor; @@ -370,7 +367,7 @@ static spl_ptr_heap *spl_ptr_heap_clone(spl_ptr_heap *from) { /* {{{ */ heap->elements = safe_emalloc(from->elem_size, from->max_size, 0); memcpy(heap->elements, from->elements, from->elem_size * from->max_size); - for (i = 0; i < heap->count; ++i) { + for (size_t i = 0; i < heap->count; ++i) { heap->ctor(spl_heap_elem(heap, i)); } @@ -384,11 +381,9 @@ static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */ return; } - int i; - heap->flags |= SPL_HEAP_WRITE_LOCKED; - for (i = 0; i < heap->count; ++i) { + for (size_t i = 0; i < heap->count; ++i) { heap->dtor(spl_heap_elem(heap, i)); } @@ -399,7 +394,7 @@ static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */ } /* }}} */ -static int spl_ptr_heap_count(spl_ptr_heap *heap) { /* {{{ */ +static size_t spl_ptr_heap_count(spl_ptr_heap *heap) { /* {{{ */ return heap->count; } /* }}} */ @@ -534,7 +529,7 @@ static HashTable* spl_heap_object_get_debug_info(const zend_class_entry *ce, zen array_init(&heap_array); - for (zend_ulong i = 0; i < intern->heap->count; ++i) { + for (size_t i = 0; i < intern->heap->count; ++i) { if (ce == spl_ce_SplPriorityQueue) { spl_pqueue_elem *pq_elem = spl_heap_elem(intern->heap, i); zval elem; diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 677590cc89514..1ae4dae1eaa35 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -2115,14 +2115,27 @@ static zend_object *spl_dual_it_new(zend_class_entry *class_type) } /* }}} */ +/* Returns the relative position for the current iterator position. */ +static zend_long spl_limit_it_relative_pos(spl_dual_it_object *intern) +{ + return intern->current.pos - intern->u.limit.offset; +} + +/* Returns the relative position for an arbitrary position. */ +static zend_long spl_limit_it_relative_pos_for(spl_dual_it_object *intern, zend_long pos) +{ + return pos - intern->u.limit.offset; +} + static inline zend_result spl_limit_it_valid(spl_dual_it_object *intern) { /* FAILURE / SUCCESS */ - if (intern->u.limit.count != -1 && intern->current.pos >= intern->u.limit.offset + intern->u.limit.count) { + if (intern->u.limit.count != -1 && + spl_limit_it_relative_pos(intern) >= intern->u.limit.count) { return FAILURE; - } else { - return spl_dual_it_valid(intern); } + + return spl_dual_it_valid(intern); } static inline void spl_limit_it_seek(spl_dual_it_object *intern, zend_long pos) @@ -2134,7 +2147,7 @@ static inline void spl_limit_it_seek(spl_dual_it_object *intern, zend_long pos) zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is below the offset " ZEND_LONG_FMT, pos, intern->u.limit.offset); return; } - if (pos - intern->u.limit.offset >= intern->u.limit.count && intern->u.limit.count != -1) { + if (spl_limit_it_relative_pos_for(intern, pos) >= intern->u.limit.count && intern->u.limit.count != -1) { zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is behind offset " ZEND_LONG_FMT " plus count " ZEND_LONG_FMT, pos, intern->u.limit.offset, intern->u.limit.count); return; } @@ -2191,7 +2204,7 @@ PHP_METHOD(LimitIterator, valid) SPL_FETCH_AND_CHECK_DUAL_IT(intern, ZEND_THIS); /* RETURN_BOOL(spl_limit_it_valid(intern) == SUCCESS);*/ - RETURN_BOOL((intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) && Z_TYPE(intern->current.data) != IS_UNDEF); + RETURN_BOOL((intern->u.limit.count == -1 || spl_limit_it_relative_pos(intern) < intern->u.limit.count) && Z_TYPE(intern->current.data) != IS_UNDEF); } /* }}} */ /* {{{ Move the iterator forward */ @@ -2204,7 +2217,7 @@ PHP_METHOD(LimitIterator, next) SPL_FETCH_AND_CHECK_DUAL_IT(intern, ZEND_THIS); spl_dual_it_next(intern, 1); - if (intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) { + if (intern->u.limit.count == -1 || spl_limit_it_relative_pos(intern) < intern->u.limit.count) { spl_dual_it_fetch(intern, 1); } } /* }}} */ diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index e6e6786c1c23b..540e5c2c0ff94 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -25,6 +25,7 @@ #include "zend_smart_str.h" #include "zend_interfaces.h" #include "zend_exceptions.h" +#include "zend_attributes.h" #include "php_spl.h" /* For php_spl_object_hash() */ #include "spl_observer.h" @@ -39,6 +40,7 @@ PHPAPI zend_class_entry *spl_ce_SplObjectStorage; PHPAPI zend_class_entry *spl_ce_MultipleIterator; static zend_object_handlers spl_handler_SplObjectStorage; +static zend_object_handlers spl_handler_MultipleIterator; /* Bit flags for marking internal functionality overridden by SplObjectStorage subclasses. */ #define SOS_OVERRIDDEN_READ_DIMENSION 1 @@ -487,6 +489,20 @@ static void spl_object_storage_write_dimension(zend_object *object, zval *offset spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf); } +static void spl_multiple_iterator_write_dimension(zend_object *object, zval *offset, zval *inf) +{ + spl_SplObjectStorage *intern = spl_object_storage_from_obj(object); + if (UNEXPECTED(offset == NULL || Z_TYPE_P(offset) != IS_OBJECT || (intern->flags & SOS_OVERRIDDEN_WRITE_DIMENSION))) { + zend_std_write_dimension(object, offset, inf); + return; + } + if (UNEXPECTED(!Z_OBJCE_P(offset)->iterator_funcs_ptr || !Z_OBJCE_P(offset)->iterator_funcs_ptr->zf_valid)) { + zend_type_error("Can only attach objects that implement the Iterator interface"); + return; + } + spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf); +} + static void spl_object_storage_unset_dimension(zend_object *object, zval *offset) { spl_SplObjectStorage *intern = spl_object_storage_from_obj(object); @@ -1389,9 +1405,13 @@ PHP_MINIT_FUNCTION(spl_observer) spl_handler_SplObjectStorage.has_dimension = spl_object_storage_has_dimension; spl_handler_SplObjectStorage.unset_dimension = spl_object_storage_unset_dimension; + memcpy(&spl_handler_MultipleIterator, &spl_handler_SplObjectStorage, sizeof(zend_object_handlers)); + + spl_handler_MultipleIterator.write_dimension = spl_multiple_iterator_write_dimension; + spl_ce_MultipleIterator = register_class_MultipleIterator(zend_ce_iterator); spl_ce_MultipleIterator->create_object = spl_SplObjectStorage_new; - spl_ce_MultipleIterator->default_object_handlers = &spl_handler_SplObjectStorage; + spl_ce_MultipleIterator->default_object_handlers = &spl_handler_MultipleIterator; return SUCCESS; } diff --git a/ext/spl/spl_observer.stub.php b/ext/spl/spl_observer.stub.php index 9e78272cf3506..1a3c1f68433b1 100644 --- a/ext/spl/spl_observer.stub.php +++ b/ext/spl/spl_observer.stub.php @@ -23,12 +23,15 @@ public function notify(): void; class SplObjectStorage implements Countable, SeekableIterator, Serializable, ArrayAccess { /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: "use method SplObjectStorage::offsetSet() instead")] public function attach(object $object, mixed $info = null): void {} /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: "use method SplObjectStorage::offsetUnset() instead")] public function detach(object $object): void {} /** @tentative-return-type */ + #[\Deprecated(since: '8.5', message: "use method SplObjectStorage::offsetExists() instead")] public function contains(object $object): bool {} /** @tentative-return-type */ diff --git a/ext/spl/spl_observer_arginfo.h b/ext/spl/spl_observer_arginfo.h index be12c594e0146..ae648edd7e818 100644 --- a/ext/spl/spl_observer_arginfo.h +++ b/ext/spl/spl_observer_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a846c9dd240b6f0666cd5e805abfacabe360cf4c */ + * Stub hash: 9dfd8bcf8946cbee550c9a46da07c424c3505408 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplObserver_update, 0, 1, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, subject, SplSubject, 0) @@ -185,9 +185,9 @@ static const zend_function_entry class_SplSubject_methods[] = { }; static const zend_function_entry class_SplObjectStorage_methods[] = { - ZEND_ME(SplObjectStorage, attach, arginfo_class_SplObjectStorage_attach, ZEND_ACC_PUBLIC) - ZEND_ME(SplObjectStorage, detach, arginfo_class_SplObjectStorage_detach, ZEND_ACC_PUBLIC) - ZEND_ME(SplObjectStorage, contains, arginfo_class_SplObjectStorage_contains, ZEND_ACC_PUBLIC) + ZEND_ME(SplObjectStorage, attach, arginfo_class_SplObjectStorage_attach, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) + ZEND_ME(SplObjectStorage, detach, arginfo_class_SplObjectStorage_detach, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) + ZEND_ME(SplObjectStorage, contains, arginfo_class_SplObjectStorage_contains, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(SplObjectStorage, addAll, arginfo_class_SplObjectStorage_addAll, ZEND_ACC_PUBLIC) ZEND_ME(SplObjectStorage, removeAll, arginfo_class_SplObjectStorage_removeAll, ZEND_ACC_PUBLIC) ZEND_ME(SplObjectStorage, removeAllExcept, arginfo_class_SplObjectStorage_removeAllExcept, ZEND_ACC_PUBLIC) @@ -258,6 +258,28 @@ static zend_class_entry *register_class_SplObjectStorage(zend_class_entry *class class_entry = zend_register_internal_class_with_flags(&ce, NULL, 0); zend_class_implements(class_entry, 4, class_entry_Countable, class_entry_SeekableIterator, class_entry_Serializable, class_entry_ArrayAccess); + + zend_attribute *attribute_Deprecated_func_attach_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "attach", sizeof("attach") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_attach_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_attach_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_attach_0_arg1_str = zend_string_init("use method SplObjectStorage::offsetSet() instead", strlen("use method SplObjectStorage::offsetSet() instead"), 1); + ZVAL_STR(&attribute_Deprecated_func_attach_0->args[1].value, attribute_Deprecated_func_attach_0_arg1_str); + attribute_Deprecated_func_attach_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_detach_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "detach", sizeof("detach") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_detach_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_detach_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_detach_0_arg1_str = zend_string_init("use method SplObjectStorage::offsetUnset() instead", strlen("use method SplObjectStorage::offsetUnset() instead"), 1); + ZVAL_STR(&attribute_Deprecated_func_detach_0->args[1].value, attribute_Deprecated_func_detach_0_arg1_str); + attribute_Deprecated_func_detach_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_contains_0 = zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "contains", sizeof("contains") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_contains_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_contains_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_contains_0_arg1_str = zend_string_init("use method SplObjectStorage::offsetExists() instead", strlen("use method SplObjectStorage::offsetExists() instead"), 1); + ZVAL_STR(&attribute_Deprecated_func_contains_0->args[1].value, attribute_Deprecated_func_contains_0_arg1_str); + attribute_Deprecated_func_contains_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + return class_entry; } diff --git a/ext/spl/tests/ArrayObject__serialize_saves_iterator_class.phpt b/ext/spl/tests/ArrayObject/ArrayObject__serialize_saves_iterator_class.phpt similarity index 100% rename from ext/spl/tests/ArrayObject__serialize_saves_iterator_class.phpt rename to ext/spl/tests/ArrayObject/ArrayObject__serialize_saves_iterator_class.phpt diff --git a/ext/spl/tests/ArrayObject_clone_other_std_props.phpt b/ext/spl/tests/ArrayObject/ArrayObject_clone_other_std_props.phpt similarity index 64% rename from ext/spl/tests/ArrayObject_clone_other_std_props.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_clone_other_std_props.phpt index 688954c3d7b13..f527f5b664586 100644 --- a/ext/spl/tests/ArrayObject_clone_other_std_props.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_clone_other_std_props.phpt @@ -9,7 +9,8 @@ $c = clone $b; var_dump($c); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(ArrayObject)#3 (1) { ["storage":"ArrayObject":private]=> array(3) { diff --git a/ext/spl/tests/ArrayObject_dump_during_sort.phpt b/ext/spl/tests/ArrayObject/ArrayObject_dump_during_sort.phpt similarity index 100% rename from ext/spl/tests/ArrayObject_dump_during_sort.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_dump_during_sort.phpt diff --git a/ext/spl/tests/ArrayObject_enum.phpt b/ext/spl/tests/ArrayObject/ArrayObject_enum.phpt similarity index 57% rename from ext/spl/tests/ArrayObject_enum.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_enum.phpt index 906c89b54dff1..a88da8fc5539c 100644 --- a/ext/spl/tests/ArrayObject_enum.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_enum.phpt @@ -11,5 +11,7 @@ new ArrayObject(Foo::Bar); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + Fatal error: Uncaught InvalidArgumentException: Enums are not compatible with ArrayObject in %s:%d %a diff --git a/ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt b/ext/spl/tests/ArrayObject/ArrayObject_exchange_array_during_sorting.phpt similarity index 100% rename from ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_exchange_array_during_sorting.phpt diff --git a/ext/spl/tests/ArrayObject_get_object_vars.phpt b/ext/spl/tests/ArrayObject/ArrayObject_get_object_vars.phpt similarity index 69% rename from ext/spl/tests/ArrayObject_get_object_vars.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_get_object_vars.phpt index a80add6b95ad7..2e6b3d27f1566 100644 --- a/ext/spl/tests/ArrayObject_get_object_vars.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_get_object_vars.phpt @@ -21,7 +21,8 @@ var_dump(get_object_vars($ao)); var_dump($ao->getObjectVars()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d array(0) { } array(1) { diff --git a/ext/spl/tests/ArrayObject_illegal_offset.phpt b/ext/spl/tests/ArrayObject/ArrayObject_illegal_offset.phpt similarity index 100% rename from ext/spl/tests/ArrayObject_illegal_offset.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_illegal_offset.phpt diff --git a/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt b/ext/spl/tests/ArrayObject/ArrayObject_modify_shared_object_properties.phpt similarity index 58% rename from ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_modify_shared_object_properties.phpt index 24c247cabd9d0..69424204456b4 100644 --- a/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_modify_shared_object_properties.phpt @@ -10,7 +10,8 @@ $ao['a'] = 42; var_dump($arr); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d array(2) { ["a"]=> int(1) diff --git a/ext/spl/tests/ArrayObject_overloaded_SplFixedArray.phpt b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_SplFixedArray.phpt similarity index 69% rename from ext/spl/tests/ArrayObject_overloaded_SplFixedArray.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_overloaded_SplFixedArray.phpt index f46e4cc1c9aa4..13065b4ac38a9 100644 --- a/ext/spl/tests/ArrayObject_overloaded_SplFixedArray.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_SplFixedArray.phpt @@ -12,5 +12,6 @@ try { echo $e->getMessage(), "\n"; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d Overloaded object of type SplFixedArray is not compatible with ArrayObject diff --git a/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_object_incompatible.phpt similarity index 71% rename from ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_overloaded_object_incompatible.phpt index 67267f0ec6a12..8cc66facc0053 100644 --- a/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_overloaded_object_incompatible.phpt @@ -12,7 +12,8 @@ try { var_dump($ao); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d Overloaded object of type DateInterval is not compatible with ArrayObject object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/ArrayObject_proptable_canonicalization.phpt b/ext/spl/tests/ArrayObject/ArrayObject_proptable_canonicalization.phpt similarity index 57% rename from ext/spl/tests/ArrayObject_proptable_canonicalization.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_proptable_canonicalization.phpt index 006a152602682..fd10797f72b06 100644 --- a/ext/spl/tests/ArrayObject_proptable_canonicalization.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_proptable_canonicalization.phpt @@ -1,5 +1,5 @@ --TEST-- -When ArrayObject wraps an object, we should use proptable canonicalization +When ArrayObject wraps an object, we should use prop table canonicalization --FILE-- ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(stdClass)#1 (1) { ["0"]=> int(1) diff --git a/ext/spl/tests/ArrayObject_sort_different_backing_storage.phpt b/ext/spl/tests/ArrayObject/ArrayObject_sort_different_backing_storage.phpt similarity index 73% rename from ext/spl/tests/ArrayObject_sort_different_backing_storage.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_sort_different_backing_storage.phpt index 93dd6570791c7..34ecc1018c065 100644 --- a/ext/spl/tests/ArrayObject_sort_different_backing_storage.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_sort_different_backing_storage.phpt @@ -29,6 +29,7 @@ var_dump($ao5); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> object(stdClass)#1 (2) { @@ -38,6 +39,8 @@ object(ArrayObject)#2 (1) { int(2) } } + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(ArrayObject)#3 (1) { ["storage":"ArrayObject":private]=> object(ArrayObject)#2 (1) { @@ -51,6 +54,8 @@ object(ArrayObject)#3 (1) { } } +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + Deprecated: Creation of dynamic property ArrayObject::$a is deprecated in %s on line %d Deprecated: Creation of dynamic property ArrayObject::$b is deprecated in %s on line %d diff --git a/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt b/ext/spl/tests/ArrayObject/ArrayObject_std_props_no_recursion.phpt similarity index 65% rename from ext/spl/tests/ArrayObject_std_props_no_recursion.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_std_props_no_recursion.phpt index 55ec57762fa4e..56f54844580d9 100644 --- a/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt +++ b/ext/spl/tests/ArrayObject/ArrayObject_std_props_no_recursion.phpt @@ -16,6 +16,8 @@ var_dump((array) $c); --EXPECTF-- Deprecated: Creation of dynamic property ArrayObject::$prop is deprecated in %s on line %d +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + Deprecated: Creation of dynamic property ArrayObject::$prop is deprecated in %s on line %d array(3) { [0]=> @@ -26,6 +28,8 @@ array(3) { int(3) } +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + Deprecated: Creation of dynamic property ArrayObject::$prop is deprecated in %s on line %d array(1) { ["prop"]=> diff --git a/ext/spl/tests/ArrayObject_unserialize_empty_string.phpt b/ext/spl/tests/ArrayObject/ArrayObject_unserialize_empty_string.phpt similarity index 100% rename from ext/spl/tests/ArrayObject_unserialize_empty_string.phpt rename to ext/spl/tests/ArrayObject/ArrayObject_unserialize_empty_string.phpt diff --git a/ext/spl/tests/arrayIterator_ksort_basic1.phpt b/ext/spl/tests/ArrayObject/arrayIterator_ksort_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayIterator_ksort_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayIterator_ksort_basic1.phpt diff --git a/ext/spl/tests/arrayObject___construct_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic1.phpt similarity index 65% rename from ext/spl/tests/arrayObject___construct_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_basic1.phpt index a14166c35e306..744a936276bdc 100644 --- a/ext/spl/tests/arrayObject___construct_basic1.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic1.phpt @@ -16,7 +16,7 @@ var_dump(new ArrayObject(array('key1' => 'val1'))); echo "--> Nested ArrayObject argument:\n"; var_dump(new ArrayObject(new ArrayObject($a))); ?> ---EXPECT-- +--EXPECTF-- --> No arguments: object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> @@ -24,6 +24,8 @@ object(ArrayObject)#1 (1) { } } --> Object argument: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> object(stdClass)#1 (1) { @@ -40,6 +42,10 @@ object(ArrayObject)#2 (1) { } } --> Nested ArrayObject argument: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> object(ArrayObject)#3 (1) { diff --git a/ext/spl/tests/arrayObject___construct_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic2.phpt similarity index 85% rename from ext/spl/tests/arrayObject___construct_basic2.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_basic2.phpt index 0d993a14e786b..e1d9718b4e625 100644 --- a/ext/spl/tests/arrayObject___construct_basic2.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic2.phpt @@ -48,6 +48,8 @@ function testAccess($c, $ao) { ?> --EXPECTF-- --> Access prop on instance of ArrayObject: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: @@ -78,6 +80,8 @@ object(C)#1 (0) { } --> Access prop on instance of MyArrayObject: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: diff --git a/ext/spl/tests/arrayObject___construct_basic3.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic3.phpt similarity index 86% rename from ext/spl/tests/arrayObject___construct_basic3.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_basic3.phpt index 3fb4dda5a6e97..135d87e6a843c 100644 --- a/ext/spl/tests/arrayObject___construct_basic3.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic3.phpt @@ -48,6 +48,8 @@ function testAccess($c, $ao) { ?> --EXPECTF-- --> Access prop on instance of ArrayObject with ArrayObject::STD_PROP_LIST: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: @@ -78,6 +80,8 @@ object(C)#1 (0) { } --> Access prop on instance of MyArrayObject with ArrayObject::STD_PROP_LIST: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: diff --git a/ext/spl/tests/arrayObject___construct_basic4.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic4.phpt similarity index 86% rename from ext/spl/tests/arrayObject___construct_basic4.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_basic4.phpt index dd8e75af9318c..2aeed29178a03 100644 --- a/ext/spl/tests/arrayObject___construct_basic4.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic4.phpt @@ -48,6 +48,8 @@ function testAccess($c, $ao) { ?> --EXPECTF-- --> Access prop on instance of ArrayObject with ArrayObject::ARRAY_AS_PROPS: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: @@ -76,6 +78,8 @@ object(C)#1 (0) { } --> Access prop on instance of MyArrayObject with ArrayObject::ARRAY_AS_PROPS: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: diff --git a/ext/spl/tests/arrayObject___construct_basic5.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic5.phpt similarity index 87% rename from ext/spl/tests/arrayObject___construct_basic5.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_basic5.phpt index e10dcd8a8d01b..125f55d06371d 100644 --- a/ext/spl/tests/arrayObject___construct_basic5.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic5.phpt @@ -48,6 +48,8 @@ function testAccess($c, $ao) { ?> --EXPECTF-- --> Access prop on instance of ArrayObject with ArrayObject::STD_PROP_LIST|ArrayObject::ARRAY_AS_PROPS: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: @@ -76,6 +78,8 @@ object(C)#1 (0) { } --> Access prop on instance of MyArrayObject with ArrayObject::STD_PROP_LIST|ArrayObject::ARRAY_AS_PROPS: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d - Iteration: prop=>C::prop.orig - Read: diff --git a/ext/spl/tests/arrayObject___construct_basic6.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic6.phpt similarity index 100% rename from ext/spl/tests/arrayObject___construct_basic6.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_basic6.phpt diff --git a/ext/spl/tests/arrayObject___construct_basic7.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_basic7.phpt similarity index 71% rename from ext/spl/tests/arrayObject___construct_basic7.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_basic7.phpt index dd10b5fb6b996..98131c8c6b4da 100644 --- a/ext/spl/tests/arrayObject___construct_basic7.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject___construct_basic7.phpt @@ -10,7 +10,8 @@ $ao = new ArrayObject($o); $ao->asort(); var_dump($a, $o, $ao); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d array(2) { [0]=> int(2) diff --git a/ext/spl/tests/arrayObject___construct_error1.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_error1.phpt similarity index 100% rename from ext/spl/tests/arrayObject___construct_error1.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_error1.phpt diff --git a/ext/spl/tests/arrayObject___construct_error2.phpt b/ext/spl/tests/ArrayObject/arrayObject___construct_error2.phpt similarity index 100% rename from ext/spl/tests/arrayObject___construct_error2.phpt rename to ext/spl/tests/ArrayObject/arrayObject___construct_error2.phpt diff --git a/ext/spl/tests/arrayObject_asort_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_asort_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_asort_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_asort_basic1.phpt diff --git a/ext/spl/tests/arrayObject_asort_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject_asort_basic2.phpt similarity index 83% rename from ext/spl/tests/arrayObject_asort_basic2.phpt rename to ext/spl/tests/ArrayObject/arrayObject_asort_basic2.phpt index 21f0dee950070..772b370ad6778 100644 --- a/ext/spl/tests/arrayObject_asort_basic2.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_asort_basic2.phpt @@ -20,8 +20,10 @@ $ao1 = new ArrayObject($c); var_dump($ao1->asort()); var_dump($ao1, $c); ?> ---EXPECT-- +--EXPECTF-- *** Testing ArrayObject::asort() : basic functionality *** + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d bool(true) object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/arrayObject_clone_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_clone_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_clone_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_clone_basic1.phpt diff --git a/ext/spl/tests/arrayObject_clone_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject_clone_basic2.phpt similarity index 84% rename from ext/spl/tests/arrayObject_clone_basic2.phpt rename to ext/spl/tests/ArrayObject/arrayObject_clone_basic2.phpt index b0a82ccfbc34a..9cca59b60a9be 100644 --- a/ext/spl/tests/arrayObject_clone_basic2.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_clone_basic2.phpt @@ -17,7 +17,8 @@ $ao1['new.ao1'] = 'new element added to ao1'; $ao2['new.ao2'] = 'new element added to ao2'; var_dump($c, $ao1, $ao2); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(C)#1 (3) { ["p1"]=> string(32) "new prop added to c before clone" diff --git a/ext/spl/tests/arrayObject_clone_basic3.phpt b/ext/spl/tests/ArrayObject/arrayObject_clone_basic3.phpt similarity index 86% rename from ext/spl/tests/arrayObject_clone_basic3.phpt rename to ext/spl/tests/ArrayObject/arrayObject_clone_basic3.phpt index 214a2b87b8690..26e633bdd06aa 100644 --- a/ext/spl/tests/arrayObject_clone_basic3.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_clone_basic3.phpt @@ -23,7 +23,10 @@ $clonedOuterArrayObject['new.coAO'] = 'new element added to $clonedOuterArrayObj var_dump($wrappedObject, $innerArrayObject, $outerArrayObject, $clonedOuterArrayObject); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(C)#1 (5) { ["p"]=> string(9) "C::p.orig" diff --git a/ext/spl/tests/arrayObject_count_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_count_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_count_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_count_basic1.phpt diff --git a/ext/spl/tests/arrayObject_exchangeArray_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_exchangeArray_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic1.phpt diff --git a/ext/spl/tests/arrayObject_exchangeArray_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic2.phpt similarity index 71% rename from ext/spl/tests/arrayObject_exchangeArray_basic2.phpt rename to ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic2.phpt index 1f037e90735b7..4ba09cd388f28 100644 --- a/ext/spl/tests/arrayObject_exchangeArray_basic2.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic2.phpt @@ -45,6 +45,8 @@ object(ArrayObject)#%d (1) { } --> exchangeArray(normal object): + +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d string(18) "normal object prop" object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> @@ -55,6 +57,8 @@ object(ArrayObject)#%d (1) { } --> exchangeArray(ArrayObject): + +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d string(19) "ArrayObject element" object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> @@ -68,6 +72,8 @@ object(ArrayObject)#%d (1) { } --> exchangeArray(ArrayIterator): + +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d string(21) "ArrayIterator element" object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> @@ -81,6 +87,10 @@ object(ArrayObject)#%d (1) { } --> exchangeArray(nested ArrayObject): + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d string(26) "nested ArrayObject element" object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> @@ -94,4 +104,4 @@ object(ArrayObject)#%d (1) { } } } -} +} \ No newline at end of file diff --git a/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic3.phpt similarity index 71% rename from ext/spl/tests/arrayObject_exchangeArray_basic3.phpt rename to ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic3.phpt index 49b990be8bdf2..8db9b016fda86 100644 --- a/ext/spl/tests/arrayObject_exchangeArray_basic3.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_exchangeArray_basic3.phpt @@ -3,7 +3,7 @@ SPL: ArrayObject::exchangeArray() basic usage with object as underlying data sto --FILE-- --EXPECTF-- --> exchangeArray() with objects: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: Creation of dynamic property C::$addedToSwapIn is deprecated in %s on line %d + +Deprecated: Creation of dynamic property C::$addedToOriginal is deprecated in %s on line %d object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> object(C)#3 (2) { @@ -82,8 +90,12 @@ array(2) { --> exchangeArray() with no arg: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d Exception: ArrayObject::exchangeArray() expects exactly 1 argument, 0 given +Deprecated: Creation of dynamic property C::$addedToOriginal is deprecated in %s on line %d + Warning: Undefined variable $copy in %s on line %d object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> @@ -104,8 +116,12 @@ NULL --> exchangeArray() with bad arg type: + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayObject::exchangeArray(): Argument #1 ($array) must be of type array, null given +Deprecated: Creation of dynamic property C::$addedToOriginal is deprecated in %s on line %d + Warning: Undefined variable $copy in %s on line %d object(ArrayObject)#3 (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/ArrayObject/arrayObject_getFlags_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_getFlags_basic1.phpt new file mode 100644 index 0000000000000..35ae39862111a --- /dev/null +++ b/ext/spl/tests/ArrayObject/arrayObject_getFlags_basic1.phpt @@ -0,0 +1,36 @@ +--TEST-- +SPL: ArrayObject::getFlags() basic usage +--FILE-- +getFlags()); + +$ao = new ArrayObject(new ArrayObject(array(1,2,3)), ArrayObject::STD_PROP_LIST); +var_dump($ao->getFlags()); + +$ao = new ArrayObject(new ArrayIterator(new ArrayObject()), ArrayObject::ARRAY_AS_PROPS); +var_dump($ao->getFlags()); + +$ao = new ArrayObject(new ArrayObject(), ArrayObject::STD_PROP_LIST|ArrayObject::ARRAY_AS_PROPS); +var_dump($ao->getFlags()); + +$cao = clone $ao; +var_dump($cao->getFlags()); +?> +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +int(0) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +int(1) + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +int(2) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +int(3) +int(3) diff --git a/ext/spl/tests/ArrayObject/arrayObject_getFlags_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject_getFlags_basic2.phpt new file mode 100644 index 0000000000000..0d0111edd1ecb --- /dev/null +++ b/ext/spl/tests/ArrayObject/arrayObject_getFlags_basic2.phpt @@ -0,0 +1,30 @@ +--TEST-- +SPL: ArrayObject::getFlags() - ensure flags are passed on to nested array objects and iterators. +--FILE-- +getFlags()); + +$ao2 = new ArrayObject($ao); +var_dump($ao2->getFlags()); +var_dump($ao2->getIterator()->getFlags()); + +$ai = new ArrayIterator($ao); +var_dump($ai->getFlags()); + +$ao2 = new ArrayObject($ao, 0); +var_dump($ao2->getFlags()); + +?> +--EXPECTF-- +int(3) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +int(3) +int(3) + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d +int(3) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +int(0) diff --git a/ext/spl/tests/arrayObject_getIteratorClass_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_getIteratorClass_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_getIteratorClass_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_getIteratorClass_basic1.phpt diff --git a/ext/spl/tests/arrayObject_ksort_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_ksort_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_ksort_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_ksort_basic1.phpt diff --git a/ext/spl/tests/arrayObject_ksort_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject_ksort_basic2.phpt similarity index 82% rename from ext/spl/tests/arrayObject_ksort_basic2.phpt rename to ext/spl/tests/ArrayObject/arrayObject_ksort_basic2.phpt index 1ac3029543d8d..6e64a1c64f0d1 100644 --- a/ext/spl/tests/arrayObject_ksort_basic2.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_ksort_basic2.phpt @@ -20,8 +20,10 @@ $ao1 = new ArrayObject($c); var_dump($ao1->ksort()); var_dump($ao1, $c); ?> ---EXPECT-- +--EXPECTF-- *** Testing ArrayObject::ksort() : basic functionality *** + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d bool(true) object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/arrayObject_magicMethods1.phpt b/ext/spl/tests/ArrayObject/arrayObject_magicMethods1.phpt similarity index 95% rename from ext/spl/tests/arrayObject_magicMethods1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_magicMethods1.phpt index ce29beb7177fb..7acf8787d4ab2 100644 --- a/ext/spl/tests/arrayObject_magicMethods1.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_magicMethods1.phpt @@ -68,6 +68,8 @@ echo " Wrapping ArrayObject:\n"; var_dump($ao); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + --> Write existent, non-existent and dynamic: Original wrapped object: object(UsesMagic)#1 (5) { diff --git a/ext/spl/tests/arrayObject_magicMethods2.phpt b/ext/spl/tests/ArrayObject/arrayObject_magicMethods2.phpt similarity index 95% rename from ext/spl/tests/arrayObject_magicMethods2.phpt rename to ext/spl/tests/ArrayObject/arrayObject_magicMethods2.phpt index d28c234d54f94..da3cb624b9b55 100644 --- a/ext/spl/tests/arrayObject_magicMethods2.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_magicMethods2.phpt @@ -68,6 +68,8 @@ echo " Wrapping ArrayObject:\n"; var_dump($ao); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + --> Write existent, non-existent and dynamic: Deprecated: Creation of dynamic property ArrayObject::$a is deprecated in %s on line %d diff --git a/ext/spl/tests/arrayObject_magicMethods3.phpt b/ext/spl/tests/ArrayObject/arrayObject_magicMethods3.phpt similarity index 95% rename from ext/spl/tests/arrayObject_magicMethods3.phpt rename to ext/spl/tests/ArrayObject/arrayObject_magicMethods3.phpt index 2ff0531e01d43..04ecfde195e7e 100644 --- a/ext/spl/tests/arrayObject_magicMethods3.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_magicMethods3.phpt @@ -68,6 +68,8 @@ echo " Wrapping ArrayObject:\n"; var_dump($ao); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + --> Write existent, non-existent and dynamic: Original wrapped object: object(UsesMagic)#1 (5) { diff --git a/ext/spl/tests/arrayObject_magicMethods4.phpt b/ext/spl/tests/ArrayObject/arrayObject_magicMethods4.phpt similarity index 96% rename from ext/spl/tests/arrayObject_magicMethods4.phpt rename to ext/spl/tests/ArrayObject/arrayObject_magicMethods4.phpt index e68ef1fc47777..a4dabb86ec7cb 100644 --- a/ext/spl/tests/arrayObject_magicMethods4.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_magicMethods4.phpt @@ -71,6 +71,8 @@ echo " Wrapping ArrayObject:\n"; var_dump($ao); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + --> Write existent, non-existent and dynamic: Original wrapped object: object(C)#1 (5) { diff --git a/ext/spl/tests/arrayObject_magicMethods5.phpt b/ext/spl/tests/ArrayObject/arrayObject_magicMethods5.phpt similarity index 95% rename from ext/spl/tests/arrayObject_magicMethods5.phpt rename to ext/spl/tests/ArrayObject/arrayObject_magicMethods5.phpt index c0393ffea48fc..569d9c0bb543f 100644 --- a/ext/spl/tests/arrayObject_magicMethods5.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_magicMethods5.phpt @@ -70,7 +70,9 @@ var_dump($obj); echo " Wrapping ArrayObject:\n"; var_dump($ao); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + --> Write existent, non-existent and dynamic: In UsesMagic::__set(a,changed) In UsesMagic::__set(dynamic,new) diff --git a/ext/spl/tests/arrayObject_magicMethods6.phpt b/ext/spl/tests/ArrayObject/arrayObject_magicMethods6.phpt similarity index 96% rename from ext/spl/tests/arrayObject_magicMethods6.phpt rename to ext/spl/tests/ArrayObject/arrayObject_magicMethods6.phpt index 75151902210fb..ae4379c090948 100644 --- a/ext/spl/tests/arrayObject_magicMethods6.phpt +++ b/ext/spl/tests/ArrayObject/arrayObject_magicMethods6.phpt @@ -71,6 +71,8 @@ echo " Wrapping ArrayObject:\n"; var_dump($ao); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + --> Write existent, non-existent and dynamic: Original wrapped object: object(C)#1 (5) { diff --git a/ext/spl/tests/arrayObject_natcasesort_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_natcasesort_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_natcasesort_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_natcasesort_basic1.phpt diff --git a/ext/spl/tests/arrayObject_natsort_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_natsort_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_natsort_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_natsort_basic1.phpt diff --git a/ext/spl/tests/arrayObject_offsetExists_nullcheck.phpt b/ext/spl/tests/ArrayObject/arrayObject_offsetExists_nullcheck.phpt similarity index 100% rename from ext/spl/tests/arrayObject_offsetExists_nullcheck.phpt rename to ext/spl/tests/ArrayObject/arrayObject_offsetExists_nullcheck.phpt diff --git a/ext/spl/tests/arrayObject_setFlags_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_setFlags_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_setFlags_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_setFlags_basic1.phpt diff --git a/ext/spl/tests/arrayObject_setFlags_basic2.phpt b/ext/spl/tests/ArrayObject/arrayObject_setFlags_basic2.phpt similarity index 100% rename from ext/spl/tests/arrayObject_setFlags_basic2.phpt rename to ext/spl/tests/ArrayObject/arrayObject_setFlags_basic2.phpt diff --git a/ext/spl/tests/arrayObject_setIteratorClass_error1.phpt b/ext/spl/tests/ArrayObject/arrayObject_setIteratorClass_error1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_setIteratorClass_error1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_setIteratorClass_error1.phpt diff --git a/ext/spl/tests/arrayObject_uasort_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_uasort_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_uasort_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_uasort_basic1.phpt diff --git a/ext/spl/tests/arrayObject_uasort_error1.phpt b/ext/spl/tests/ArrayObject/arrayObject_uasort_error1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_uasort_error1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_uasort_error1.phpt diff --git a/ext/spl/tests/arrayObject_uksort_basic1.phpt b/ext/spl/tests/ArrayObject/arrayObject_uksort_basic1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_uksort_basic1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_uksort_basic1.phpt diff --git a/ext/spl/tests/arrayObject_uksort_error1.phpt b/ext/spl/tests/ArrayObject/arrayObject_uksort_error1.phpt similarity index 100% rename from ext/spl/tests/arrayObject_uksort_error1.phpt rename to ext/spl/tests/ArrayObject/arrayObject_uksort_error1.phpt diff --git a/ext/spl/tests/array_001.phpt b/ext/spl/tests/ArrayObject/array_001.phpt similarity index 100% rename from ext/spl/tests/array_001.phpt rename to ext/spl/tests/ArrayObject/array_001.phpt diff --git a/ext/spl/tests/array_002.phpt b/ext/spl/tests/ArrayObject/array_002.phpt similarity index 78% rename from ext/spl/tests/array_002.phpt rename to ext/spl/tests/ArrayObject/array_002.phpt index 94559f5bf7558..a305770edf90c 100644 --- a/ext/spl/tests/array_002.phpt +++ b/ext/spl/tests/ArrayObject/array_002.phpt @@ -18,6 +18,7 @@ var_dump($arrayObject); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(ArrayObject)#%d (1) { ["storage":"ArrayObject":private]=> object(ArrayObject)#1 (1) { diff --git a/ext/spl/tests/array_003.phpt b/ext/spl/tests/ArrayObject/array_003.phpt similarity index 84% rename from ext/spl/tests/array_003.phpt rename to ext/spl/tests/ArrayObject/array_003.phpt index 3ca23f09dc7ce..38db056250497 100644 --- a/ext/spl/tests/array_003.phpt +++ b/ext/spl/tests/ArrayObject/array_003.phpt @@ -35,7 +35,7 @@ foreach($test as $key => $val) } ?> ---EXPECT-- +--EXPECTF-- test Object ( [pub] => public @@ -44,6 +44,8 @@ test Object [imp] => implicit [dyn] => dynamic ) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayObject Object ( [storage:ArrayObject:private] => test Object diff --git a/ext/spl/tests/array_004.phpt b/ext/spl/tests/ArrayObject/array_004.phpt similarity index 100% rename from ext/spl/tests/array_004.phpt rename to ext/spl/tests/ArrayObject/array_004.phpt diff --git a/ext/spl/tests/array_005.phpt b/ext/spl/tests/ArrayObject/array_005.phpt similarity index 100% rename from ext/spl/tests/array_005.phpt rename to ext/spl/tests/ArrayObject/array_005.phpt diff --git a/ext/spl/tests/array_006.phpt b/ext/spl/tests/ArrayObject/array_006.phpt similarity index 100% rename from ext/spl/tests/array_006.phpt rename to ext/spl/tests/ArrayObject/array_006.phpt diff --git a/ext/spl/tests/array_007.phpt b/ext/spl/tests/ArrayObject/array_007.phpt similarity index 78% rename from ext/spl/tests/array_007.phpt rename to ext/spl/tests/ArrayObject/array_007.phpt index 3cdd40a1dbc70..de492257c65f4 100644 --- a/ext/spl/tests/array_007.phpt +++ b/ext/spl/tests/ArrayObject/array_007.phpt @@ -39,7 +39,7 @@ foreach($test as $key => $val) } ?> ---EXPECT-- +--EXPECTF-- test Object ( [pub] => public @@ -48,6 +48,8 @@ test Object [imp] => implicit [dyn] => dynamic ) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIterator Object ( [storage:ArrayIterator:private] => ArrayObject Object @@ -64,6 +66,8 @@ ArrayIterator Object ) ) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d pub => public imp => implicit dyn => dynamic diff --git a/ext/spl/tests/array_008.phpt b/ext/spl/tests/ArrayObject/array_008.phpt similarity index 100% rename from ext/spl/tests/array_008.phpt rename to ext/spl/tests/ArrayObject/array_008.phpt diff --git a/ext/spl/tests/array_009.phpt b/ext/spl/tests/ArrayObject/array_009.phpt similarity index 100% rename from ext/spl/tests/array_009.phpt rename to ext/spl/tests/ArrayObject/array_009.phpt diff --git a/ext/spl/tests/array_009a.phpt b/ext/spl/tests/ArrayObject/array_009a.phpt similarity index 100% rename from ext/spl/tests/array_009a.phpt rename to ext/spl/tests/ArrayObject/array_009a.phpt diff --git a/ext/spl/tests/array_010.phpt b/ext/spl/tests/ArrayObject/array_010.phpt similarity index 100% rename from ext/spl/tests/array_010.phpt rename to ext/spl/tests/ArrayObject/array_010.phpt diff --git a/ext/spl/tests/array_011.phpt b/ext/spl/tests/ArrayObject/array_011.phpt similarity index 100% rename from ext/spl/tests/array_011.phpt rename to ext/spl/tests/ArrayObject/array_011.phpt diff --git a/ext/spl/tests/array_012.phpt b/ext/spl/tests/ArrayObject/array_012.phpt similarity index 79% rename from ext/spl/tests/array_012.phpt rename to ext/spl/tests/ArrayObject/array_012.phpt index 5d5993d936947..f3b0fa9813b0c 100644 --- a/ext/spl/tests/array_012.phpt +++ b/ext/spl/tests/ArrayObject/array_012.phpt @@ -39,7 +39,7 @@ foreach($it as $key => $val) var_dump($it->count()); ?> ---EXPECT-- +--EXPECTF-- ===Array=== int(3) zero=>0 @@ -50,6 +50,8 @@ two=>2 int(3) int(3) ===Object=== + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d int(3) zero=>0 int(3) diff --git a/ext/spl/tests/array_013.phpt b/ext/spl/tests/ArrayObject/array_013.phpt similarity index 87% rename from ext/spl/tests/array_013.phpt rename to ext/spl/tests/ArrayObject/array_013.phpt index 9ad11c8f38c79..01097bac04dc1 100644 --- a/ext/spl/tests/array_013.phpt +++ b/ext/spl/tests/ArrayObject/array_013.phpt @@ -70,6 +70,8 @@ var_dump($o->{0}); /* doesn't wotk anyway */ 3=>three 4=>four ===Object=== + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d zero=>0 one=>1 two=>2 diff --git a/ext/spl/tests/array_014.phpt b/ext/spl/tests/ArrayObject/array_014.phpt similarity index 100% rename from ext/spl/tests/array_014.phpt rename to ext/spl/tests/ArrayObject/array_014.phpt diff --git a/ext/spl/tests/array_015.phpt b/ext/spl/tests/ArrayObject/array_015.phpt similarity index 100% rename from ext/spl/tests/array_015.phpt rename to ext/spl/tests/ArrayObject/array_015.phpt diff --git a/ext/spl/tests/array_016.phpt b/ext/spl/tests/ArrayObject/array_016.phpt similarity index 100% rename from ext/spl/tests/array_016.phpt rename to ext/spl/tests/ArrayObject/array_016.phpt diff --git a/ext/spl/tests/array_017.phpt b/ext/spl/tests/ArrayObject/array_017.phpt similarity index 88% rename from ext/spl/tests/array_017.phpt rename to ext/spl/tests/ArrayObject/array_017.phpt index ba4842dce20c9..2a80386b6f73c 100644 --- a/ext/spl/tests/array_017.phpt +++ b/ext/spl/tests/ArrayObject/array_017.phpt @@ -177,6 +177,8 @@ array(3) { ArrayObjectEx::show() ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> @@ -245,6 +247,8 @@ array(1) { ===FOREACH=== ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> @@ -366,6 +370,8 @@ array(3) { ArrayObjectEx::show() ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> @@ -434,6 +440,8 @@ array(1) { ===FOREACH=== ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> @@ -512,6 +520,8 @@ int(1) bool(true) #####EXCHANGE##### ArrayObjectEx::exchange() + +Deprecated: ArrayObject::exchangeArray(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d ===CHECK=== ArrayObjectEx::setFlags(0) ArrayObjectEx::dump() @@ -548,6 +558,8 @@ array(3) { ArrayObjectEx::show() ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> @@ -607,6 +619,8 @@ array(1) { ===FOREACH=== ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> @@ -710,6 +724,8 @@ array(3) { ArrayObjectEx::show() ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> @@ -769,6 +785,8 @@ array(1) { ===FOREACH=== ArrayObjectEx::getIterator() ArrayIteratorEx::__construct() + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayIteratorEx::dump() array(3) { ["Flags"]=> diff --git a/ext/spl/tests/array_018.phpt b/ext/spl/tests/ArrayObject/array_018.phpt similarity index 100% rename from ext/spl/tests/array_018.phpt rename to ext/spl/tests/ArrayObject/array_018.phpt diff --git a/ext/spl/tests/array_019.phpt b/ext/spl/tests/ArrayObject/array_019.phpt similarity index 100% rename from ext/spl/tests/array_019.phpt rename to ext/spl/tests/ArrayObject/array_019.phpt diff --git a/ext/spl/tests/array_020.phpt b/ext/spl/tests/ArrayObject/array_020.phpt similarity index 100% rename from ext/spl/tests/array_020.phpt rename to ext/spl/tests/ArrayObject/array_020.phpt diff --git a/ext/spl/tests/array_021.phpt b/ext/spl/tests/ArrayObject/array_021.phpt similarity index 100% rename from ext/spl/tests/array_021.phpt rename to ext/spl/tests/ArrayObject/array_021.phpt diff --git a/ext/spl/tests/array_022.phpt b/ext/spl/tests/ArrayObject/array_022.phpt similarity index 72% rename from ext/spl/tests/array_022.phpt rename to ext/spl/tests/ArrayObject/array_022.phpt index f7407bf602c75..4e8c94fd11815 100644 --- a/ext/spl/tests/array_022.phpt +++ b/ext/spl/tests/ArrayObject/array_022.phpt @@ -45,6 +45,8 @@ var_dump($b); ?> --EXPECTF-- ==ArrayObject=== + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(MyArrayObject)#%d (1) { ["bar"]=> string(3) "baz" @@ -56,6 +58,8 @@ object(MyArrayObject)#%d (2) { string(3) "Foo" } ==ArrayIterator=== + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d object(MyArrayIterator)#%d (1) { ["bar"]=> string(3) "baz" diff --git a/ext/spl/tests/array_023.phpt b/ext/spl/tests/ArrayObject/array_023.phpt similarity index 100% rename from ext/spl/tests/array_023.phpt rename to ext/spl/tests/ArrayObject/array_023.phpt diff --git a/ext/spl/tests/array_024.phpt b/ext/spl/tests/ArrayObject/array_024.phpt similarity index 100% rename from ext/spl/tests/array_024.phpt rename to ext/spl/tests/ArrayObject/array_024.phpt diff --git a/ext/spl/tests/array_025.phpt b/ext/spl/tests/ArrayObject/array_025.phpt similarity index 69% rename from ext/spl/tests/array_025.phpt rename to ext/spl/tests/ArrayObject/array_025.phpt index d64f8f04c1e14..4bd4c434f4804 100644 --- a/ext/spl/tests/array_025.phpt +++ b/ext/spl/tests/ArrayObject/array_025.phpt @@ -10,7 +10,10 @@ print_r($obj1); echo "$s\n"; print_r($obj2); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayObject::__unserialize(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d ArrayObject Object ( [storage:ArrayObject:private] => ArrayObject Object diff --git a/ext/spl/tests/array_026.phpt b/ext/spl/tests/ArrayObject/array_026.phpt similarity index 100% rename from ext/spl/tests/array_026.phpt rename to ext/spl/tests/ArrayObject/array_026.phpt diff --git a/ext/spl/tests/array_027.phpt b/ext/spl/tests/ArrayObject/array_027.phpt similarity index 100% rename from ext/spl/tests/array_027.phpt rename to ext/spl/tests/ArrayObject/array_027.phpt diff --git a/ext/spl/tests/array_028.phpt b/ext/spl/tests/ArrayObject/array_028.phpt similarity index 66% rename from ext/spl/tests/array_028.phpt rename to ext/spl/tests/ArrayObject/array_028.phpt index 1adcdd3f90714..1e422fe2f990b 100644 --- a/ext/spl/tests/array_028.phpt +++ b/ext/spl/tests/ArrayObject/array_028.phpt @@ -21,7 +21,9 @@ foreach ($obj as $v) { var_dump($v); } ?> ---EXPECT-- +--EXPECTF-- string(3) "bar" string(3) "bar" + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d string(3) "bar" diff --git a/ext/spl/tests/ArrayObject/asort_disabled.phpt b/ext/spl/tests/ArrayObject/asort_disabled.phpt new file mode 100644 index 0000000000000..8f2241332f72e --- /dev/null +++ b/ext/spl/tests/ArrayObject/asort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function asort() is disabled +--INI-- +disable_functions=asort +--FILE-- +asort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method asort when function asort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->asort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/bug31346.phpt b/ext/spl/tests/ArrayObject/bug31346.phpt similarity index 54% rename from ext/spl/tests/bug31346.phpt rename to ext/spl/tests/ArrayObject/bug31346.phpt index b2d29905ac767..a1088dfd013e8 100644 --- a/ext/spl/tests/bug31346.phpt +++ b/ext/spl/tests/ArrayObject/bug31346.phpt @@ -14,5 +14,6 @@ $i->next(); ?> ===DONE=== ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d ===DONE=== diff --git a/ext/spl/tests/bug38618.phpt b/ext/spl/tests/ArrayObject/bug38618.phpt similarity index 69% rename from ext/spl/tests/bug38618.phpt rename to ext/spl/tests/ArrayObject/bug38618.phpt index 71a09111a4b8b..5a865f12d636e 100644 --- a/ext/spl/tests/bug38618.phpt +++ b/ext/spl/tests/ArrayObject/bug38618.phpt @@ -84,14 +84,22 @@ test_array($array, 'Protected Property'); test_array($array, 'Public Property New', RecursiveArrayIterator::CHILD_ARRAYS_ONLY); test_array($array, 'Protected Property New', RecursiveArrayIterator::CHILD_ARRAYS_ONLY); ?> ---EXPECT-- +--EXPECTF-- ===Default with array=== 1 => apple 1 => grape ===Public Property=== + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d title => apple + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d title => grape ===Protected Property=== + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d ===Public Property New=== 1 => apple 1 => grape diff --git a/ext/spl/tests/bug41691.phpt b/ext/spl/tests/ArrayObject/bug41691.phpt similarity index 70% rename from ext/spl/tests/bug41691.phpt rename to ext/spl/tests/ArrayObject/bug41691.phpt index 93af430b4884a..c808d59c2022f 100644 --- a/ext/spl/tests/bug41691.phpt +++ b/ext/spl/tests/ArrayObject/bug41691.phpt @@ -17,7 +17,8 @@ var_dump($a->exchangeArray(array('a'=>1,'b'=>1,'c'=>1))); echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d array(3) { ["a"]=> NULL diff --git a/ext/spl/tests/bug44615.phpt b/ext/spl/tests/ArrayObject/bug44615.phpt similarity index 76% rename from ext/spl/tests/bug44615.phpt rename to ext/spl/tests/ArrayObject/bug44615.phpt index 0b9aa82bc300b..3ac30192170c6 100644 --- a/ext/spl/tests/bug44615.phpt +++ b/ext/spl/tests/ArrayObject/bug44615.phpt @@ -20,7 +20,7 @@ foreach (new RecursiveIteratorIterator($rai) as $t) { var_dump($t); } ?> ---EXPECT-- +--EXPECTF-- string(1) "z" object(stdClass)#1 (0) { } @@ -28,5 +28,7 @@ string(1) "q" string(1) "s" Second: string(1) "z" + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d string(1) "q" string(1) "s" diff --git a/ext/spl/tests/bug45614.phpt b/ext/spl/tests/ArrayObject/bug45614.phpt similarity index 87% rename from ext/spl/tests/bug45614.phpt rename to ext/spl/tests/ArrayObject/bug45614.phpt index 8c688555d3797..04c4638155359 100644 --- a/ext/spl/tests/bug45614.phpt +++ b/ext/spl/tests/ArrayObject/bug45614.phpt @@ -39,7 +39,8 @@ $ai->rewind(); $ai->seek(0); showFirstTwoItems($ai); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d --> Show the first two items: pub1 => public1 pub2 => public2 diff --git a/ext/spl/tests/bug54323.phpt b/ext/spl/tests/ArrayObject/bug54323.phpt similarity index 74% rename from ext/spl/tests/bug54323.phpt rename to ext/spl/tests/ArrayObject/bug54323.phpt index 7431c9c47348a..fa1e64f4947c2 100644 --- a/ext/spl/tests/bug54323.phpt +++ b/ext/spl/tests/ArrayObject/bug54323.phpt @@ -18,6 +18,8 @@ function testAccess($c, $ao) { } ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + Warning: Undefined property: C::$prop in %s on line %d Warning: Undefined array key "prop" in %s on line %d diff --git a/ext/spl/tests/bug62672.phpt b/ext/spl/tests/ArrayObject/bug62672.phpt similarity index 71% rename from ext/spl/tests/bug62672.phpt rename to ext/spl/tests/ArrayObject/bug62672.phpt index ec40ee695504b..2d70ca71a1bd4 100644 --- a/ext/spl/tests/bug62672.phpt +++ b/ext/spl/tests/ArrayObject/bug62672.phpt @@ -28,5 +28,6 @@ $obj = new ObjB(new ArrayObject()); var_dump($obj == unserialize(serialize($obj))); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__unserialize(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d bool(true) diff --git a/ext/spl/tests/ArrayObject/bug69845.phpt b/ext/spl/tests/ArrayObject/bug69845.phpt new file mode 100644 index 0000000000000..6554e290e03a5 --- /dev/null +++ b/ext/spl/tests/ArrayObject/bug69845.phpt @@ -0,0 +1,16 @@ +--TEST-- +Fixed bug #69845 (ArrayObject with ARRAY_AS_PROPS broken) +--FILE-- +itemType = 'bulletin'; + var_dump(!is_null($data['itemType'])); +} +?> +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +bool(true) + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d +bool(true) diff --git a/ext/spl/tests/bug70155.phpt b/ext/spl/tests/ArrayObject/bug70155.phpt similarity index 75% rename from ext/spl/tests/bug70155.phpt rename to ext/spl/tests/ArrayObject/bug70155.phpt index a609205aca279..27521015c4872 100644 --- a/ext/spl/tests/bug70155.phpt +++ b/ext/spl/tests/ArrayObject/bug70155.phpt @@ -9,6 +9,8 @@ $data = unserialize($exploit); var_dump($data); ?> --EXPECTF-- +Deprecated: ArrayObject::unserialize(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + Deprecated: Creation of dynamic property ArrayObject::$0 is deprecated in %s on line %d Fatal error: Uncaught InvalidArgumentException: Overloaded object of type DateInterval is not compatible with ArrayObject in %s diff --git a/ext/spl/tests/bug73209.phpt b/ext/spl/tests/ArrayObject/bug73209.phpt similarity index 74% rename from ext/spl/tests/bug73209.phpt rename to ext/spl/tests/ArrayObject/bug73209.phpt index 7383940936689..7da582b13523a 100644 --- a/ext/spl/tests/bug73209.phpt +++ b/ext/spl/tests/ArrayObject/bug73209.phpt @@ -19,7 +19,8 @@ foreach($iterator as $k=>$v) { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d Expect to see all keys in ->props here: props hello diff --git a/ext/spl/tests/bug74669.phpt b/ext/spl/tests/ArrayObject/bug74669.phpt similarity index 76% rename from ext/spl/tests/bug74669.phpt rename to ext/spl/tests/ArrayObject/bug74669.phpt index 597e694296d26..17f622aaaf9d0 100644 --- a/ext/spl/tests/bug74669.phpt +++ b/ext/spl/tests/ArrayObject/bug74669.phpt @@ -93,13 +93,20 @@ var_dump($selfArray['foo']); ?> --EXPECTF-- +Deprecated: ArrayIterator::__unserialize(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d 0 => test1 1 => test2 + +Deprecated: ArrayIterator::__unserialize(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d 0 => test1 1 => test2 +Deprecated: ArrayObject::unserialize(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d + Warning: Undefined array key "foo" in %s on line %d NULL + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d object(SelfArray)#9 (1) { ["foo"]=> string(3) "bar" diff --git a/ext/spl/tests/gh10519.phpt b/ext/spl/tests/ArrayObject/gh10519.phpt similarity index 88% rename from ext/spl/tests/gh10519.phpt rename to ext/spl/tests/ArrayObject/gh10519.phpt index 1f7572d6e8ca6..5ef7fb3144f92 100644 --- a/ext/spl/tests/gh10519.phpt +++ b/ext/spl/tests/ArrayObject/gh10519.phpt @@ -62,7 +62,8 @@ $example->bugySetMethod(5, 'must be here'); var_dump(json_encode($example)); var_dump(json_encode($b)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d string(51) "{"test":{"a":{"2":"","3":"","4":"","5":"in here"}}}" string(51) "{"test":{"a":{"2":"","3":"","4":"","5":"in here"}}}" string(56) "{"test":{"b":{"2":"","3":"","4":"","5":"must be here"}}}" diff --git a/ext/spl/tests/gh11178.phpt b/ext/spl/tests/ArrayObject/gh11178.phpt similarity index 69% rename from ext/spl/tests/gh11178.phpt rename to ext/spl/tests/ArrayObject/gh11178.phpt index 3732c57a59d19..91ac55d6f814a 100644 --- a/ext/spl/tests/gh11178.phpt +++ b/ext/spl/tests/ArrayObject/gh11178.phpt @@ -21,7 +21,8 @@ foreach ($obj as $k => &$v) { var_dump($obj); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d object(A)#1 (1) { ["x"]=> &int(3) diff --git a/ext/spl/tests/gh15833_1.phpt b/ext/spl/tests/ArrayObject/gh15833_1.phpt similarity index 71% rename from ext/spl/tests/gh15833_1.phpt rename to ext/spl/tests/ArrayObject/gh15833_1.phpt index d658a770e80f5..5ee4b69e32560 100644 --- a/ext/spl/tests/gh15833_1.phpt +++ b/ext/spl/tests/ArrayObject/gh15833_1.phpt @@ -17,6 +17,7 @@ var_dump($recursiveArrayIterator->current()); $recursiveArrayIterator->next(); var_dump($recursiveArrayIterator->current()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d int(1) NULL diff --git a/ext/spl/tests/gh15833_2.phpt b/ext/spl/tests/ArrayObject/gh15833_2.phpt similarity index 81% rename from ext/spl/tests/gh15833_2.phpt rename to ext/spl/tests/ArrayObject/gh15833_2.phpt index 8f30921741fe3..5d7721e25dd24 100644 --- a/ext/spl/tests/gh15833_2.phpt +++ b/ext/spl/tests/ArrayObject/gh15833_2.phpt @@ -34,7 +34,8 @@ try { echo $e->getMessage(), "\n"; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d nope 0 nope 1 nope 2 diff --git a/ext/spl/tests/gh15918.phpt b/ext/spl/tests/ArrayObject/gh15918.phpt similarity index 61% rename from ext/spl/tests/gh15918.phpt rename to ext/spl/tests/ArrayObject/gh15918.phpt index b26ff8adfc140..5efdb887f9b56 100644 --- a/ext/spl/tests/gh15918.phpt +++ b/ext/spl/tests/ArrayObject/gh15918.phpt @@ -9,5 +9,6 @@ try { echo $e->getMessage(), "\n"; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d Overloaded object of type SplFixedArray is not compatible with ArrayObject diff --git a/ext/spl/tests/gh16646.phpt b/ext/spl/tests/ArrayObject/gh16646.phpt similarity index 71% rename from ext/spl/tests/gh16646.phpt rename to ext/spl/tests/ArrayObject/gh16646.phpt index b6cb503d8ed05..f572346ea5dfa 100644 --- a/ext/spl/tests/gh16646.phpt +++ b/ext/spl/tests/ArrayObject/gh16646.phpt @@ -23,7 +23,8 @@ unset($arr["b"]); var_dump($arr); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d C::__destruct object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/gh16646_2.phpt b/ext/spl/tests/ArrayObject/gh16646_2.phpt similarity index 67% rename from ext/spl/tests/gh16646_2.phpt rename to ext/spl/tests/ArrayObject/gh16646_2.phpt index d006583500811..035087fbe22bb 100644 --- a/ext/spl/tests/gh16646_2.phpt +++ b/ext/spl/tests/ArrayObject/gh16646_2.phpt @@ -16,7 +16,8 @@ $arr->exchangeArray([]); var_dump($arr); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d C::__destruct object(ArrayObject)#1 (1) { ["storage":"ArrayObject":private]=> diff --git a/ext/spl/tests/ArrayObject/ksort_disabled.phpt b/ext/spl/tests/ArrayObject/ksort_disabled.phpt new file mode 100644 index 0000000000000..258057ad64d31 --- /dev/null +++ b/ext/spl/tests/ArrayObject/ksort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function ksort() is disabled +--INI-- +disable_functions=ksort +--FILE-- +ksort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method ksort when function ksort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->ksort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/natcasesort_disabled.phpt b/ext/spl/tests/ArrayObject/natcasesort_disabled.phpt new file mode 100644 index 0000000000000..336e1245dabc5 --- /dev/null +++ b/ext/spl/tests/ArrayObject/natcasesort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function natcasesort() is disabled +--INI-- +disable_functions=natcasesort +--FILE-- +natcasesort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method natcasesort when function natcasesort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->natcasesort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/natsort_disabled.phpt b/ext/spl/tests/ArrayObject/natsort_disabled.phpt new file mode 100644 index 0000000000000..b674235627adb --- /dev/null +++ b/ext/spl/tests/ArrayObject/natsort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function natsort() is disabled +--INI-- +disable_functions=natsort +--FILE-- +natsort(); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method natsort when function natsort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->natsort() +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/property_hooks.phpt b/ext/spl/tests/ArrayObject/property_hooks.phpt index c0b2a372ebe4c..dfed649e7c630 100644 --- a/ext/spl/tests/ArrayObject/property_hooks.phpt +++ b/ext/spl/tests/ArrayObject/property_hooks.phpt @@ -63,6 +63,7 @@ var_dump($o->username); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d Check object properties directly string(5) "FIRST" string(4) "last" diff --git a/ext/spl/tests/ArrayObject/uasort_disabled.phpt b/ext/spl/tests/ArrayObject/uasort_disabled.phpt new file mode 100644 index 0000000000000..5a5e9aa57b21a --- /dev/null +++ b/ext/spl/tests/ArrayObject/uasort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function uasort() is disabled +--INI-- +disable_functions=uasort +--FILE-- +uasort(fn ($l, $r) => $l <=> $r); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method uasort when function uasort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->uasort(Object(Closure)) +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/ArrayObject/uksort_disabled.phpt b/ext/spl/tests/ArrayObject/uksort_disabled.phpt new file mode 100644 index 0000000000000..af703883a3f55 --- /dev/null +++ b/ext/spl/tests/ArrayObject/uksort_disabled.phpt @@ -0,0 +1,18 @@ +--TEST-- +ArrayObject when function uksort() is disabled +--INI-- +disable_functions=uksort +--FILE-- +uksort(fn ($l, $r) => $l <=> $r); +var_dump($ao); + +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call method uksort when function uksort is disabled in %s:%d +Stack trace: +#0 %s(%d): ArrayObject->uksort(Object(Closure)) +#1 {main} + thrown in %s on line %d diff --git a/ext/spl/tests/SplObjectStorage/SplObjectStorage_coalesce.phpt b/ext/spl/tests/SplObjectStorage/SplObjectStorage_coalesce.phpt index 5a89b46be6b8f..d4075018d3415 100644 --- a/ext/spl/tests/SplObjectStorage/SplObjectStorage_coalesce.phpt +++ b/ext/spl/tests/SplObjectStorage/SplObjectStorage_coalesce.phpt @@ -19,15 +19,17 @@ var_dump(isset($s[$o2])); var_dump(empty($s[$o2])); $s[$o2] = null; var_dump($s[$o2] ?? new stdClass()); -echo "check isset/empty/contains for null. offsetExists returns true as long as the entry is there.\n"; +echo "check isset/empty/contains/offsetExists for null. offsetExists returns true as long as the entry is there.\n"; var_dump(isset($s[$o2])); var_dump(empty($s[$o2])); var_dump($s->contains($o2)); -echo "check isset/empty/contains for false.\n"; +var_dump($s->offsetExists($o2)); +echo "check isset/empty/contains/offsetExists for false.\n"; $s[$o2] = false; var_dump(isset($s[$o2])); var_dump(empty($s[$o2])); var_dump($s->contains($o2)); +var_dump($s->offsetExists($o2)); try { $s['invalid'] = 123; } catch (Error $e) { @@ -56,18 +58,24 @@ bool(false) bool(true) object(stdClass)#4 (0) { } -check isset/empty/contains for null. offsetExists returns true as long as the entry is there. +check isset/empty/contains/offsetExists for null. offsetExists returns true as long as the entry is there. bool(true) bool(true) + +Deprecated: Method SplObjectStorage::contains() is deprecated since 8.5, use method SplObjectStorage::offsetExists() instead in %s on line %d +bool(true) bool(true) -check isset/empty/contains for false. +check isset/empty/contains/offsetExists for false. bool(true) bool(true) + +Deprecated: Method SplObjectStorage::contains() is deprecated since 8.5, use method SplObjectStorage::offsetExists() instead in %s on line %d +bool(true) bool(true) TypeError: SplObjectStorage::offsetSet(): Argument #1 ($object) must be of type object, string given TypeError: SplObjectStorage::offsetExists(): Argument #1 ($object) must be of type object, string given -Notice: Indirect modification of overloaded element of SplObjectStorage has no effect in %s on line 38 +Notice: Indirect modification of overloaded element of SplObjectStorage has no effect in %s on line %d object(SplObjectStorage)#1 (1) { ["storage":"SplObjectStorage":private]=> array(2) { diff --git a/ext/spl/tests/SplObjectStorage/SplObjectStorage_removeAllExcept_basic.phpt b/ext/spl/tests/SplObjectStorage/SplObjectStorage_removeAllExcept_basic.phpt index a6059da2958f2..fa7fdf367fa90 100644 --- a/ext/spl/tests/SplObjectStorage/SplObjectStorage_removeAllExcept_basic.phpt +++ b/ext/spl/tests/SplObjectStorage/SplObjectStorage_removeAllExcept_basic.phpt @@ -10,16 +10,16 @@ $b = (object) 'b'; $c = (object) 'c'; $foo = new SplObjectStorage; -$foo->attach($a); -$foo->attach($b); +$foo->offsetSet($a); +$foo->offsetSet($b); $bar = new SplObjectStorage; -$bar->attach($b); -$bar->attach($c); +$bar->offsetSet($b); +$bar->offsetSet($c); $foo->removeAllExcept($bar); -var_dump($foo->contains($a)); -var_dump($foo->contains($b)); +var_dump($foo->offsetExists($a)); +var_dump($foo->offsetExists($b)); ?> --EXPECT-- diff --git a/ext/spl/tests/SplObjectStorage_seek.phpt b/ext/spl/tests/SplObjectStorage/SplObjectStorage_seek.phpt similarity index 97% rename from ext/spl/tests/SplObjectStorage_seek.phpt rename to ext/spl/tests/SplObjectStorage/SplObjectStorage_seek.phpt index f51a285d06007..ce21b2a621fe2 100644 --- a/ext/spl/tests/SplObjectStorage_seek.phpt +++ b/ext/spl/tests/SplObjectStorage/SplObjectStorage_seek.phpt @@ -64,8 +64,8 @@ var_dump($storage->current()); echo "--- With holes cases ---\n"; -$storage->detach($b); -$storage->detach($d); +$storage->offsetUnset($b); +$storage->offsetUnset($d); foreach (range(0, 2) as $index) { $storage->seek($index); diff --git a/ext/spl/tests/SplObjectStorage/bug49263.phpt b/ext/spl/tests/SplObjectStorage/bug49263.phpt index 23bd0b272a746..a8088f180790b 100644 --- a/ext/spl/tests/SplObjectStorage/bug49263.phpt +++ b/ext/spl/tests/SplObjectStorage/bug49263.phpt @@ -7,8 +7,8 @@ $o2 = new stdClass; $s = new SplObjectStorage(); -$s->attach($o1, array('prev' => 2, 'next' => $o2)); -$s->attach($o2, array('prev' => $o1)); +$s->offsetSet($o1, array('prev' => 2, 'next' => $o2)); +$s->offsetSet($o2, array('prev' => $o1)); $ss = serialize($s); unset($s,$o1,$o2); diff --git a/ext/spl/tests/SplObjectStorage/bug53071.phpt b/ext/spl/tests/SplObjectStorage/bug53071.phpt index e3bd5e1155b3f..0f0800d13efa2 100644 --- a/ext/spl/tests/SplObjectStorage/bug53071.phpt +++ b/ext/spl/tests/SplObjectStorage/bug53071.phpt @@ -13,8 +13,8 @@ function LimitedScope() $myB = new SplObjectStorage(); $myC = new myClass(); $myC->member = $myA; // myC has a reference to myA - $myB->Attach($myC); // myB attaches myC - $myA->member = $myB; // myA has myB, comleting the cycle + $myB->offsetSet($myC); // myB attaches myC + $myA->member = $myB; // myA has myB, completing the cycle } LimitedScope(); var_dump(gc_collect_cycles()); diff --git a/ext/spl/tests/SplObjectStorage/bug67582.phpt b/ext/spl/tests/SplObjectStorage/bug67582.phpt index dc0cd532321e3..86a11e516ae10 100644 --- a/ext/spl/tests/SplObjectStorage/bug67582.phpt +++ b/ext/spl/tests/SplObjectStorage/bug67582.phpt @@ -11,7 +11,7 @@ class MyObjectStorage extends SplObjectStorage { class TestObject {} $list = new MyObjectStorage(); -$list->attach(new TestObject()); +$list->offsetSet(new TestObject()); foreach($list as $x) var_dump($list->offsetExists($x)); diff --git a/ext/spl/tests/SplObjectStorage/bug69108.phpt b/ext/spl/tests/SplObjectStorage/bug69108.phpt index 3122da599c64c..3579164791d60 100644 --- a/ext/spl/tests/SplObjectStorage/bug69108.phpt +++ b/ext/spl/tests/SplObjectStorage/bug69108.phpt @@ -9,7 +9,7 @@ $b = new SplObjectStorage(); for ($i = 10000; $i > 0; $i--) { $object = new StdClass(); $a[] = $object; - $b->attach($object); + $b->offsetSet($object); } $c = serialize(array($a, $b)); diff --git a/ext/spl/tests/SplObjectStorage/bug69227.phpt b/ext/spl/tests/SplObjectStorage/bug69227.phpt index 812d8bafd8a3b..5a527d17df3ac 100644 --- a/ext/spl/tests/SplObjectStorage/bug69227.phpt +++ b/ext/spl/tests/SplObjectStorage/bug69227.phpt @@ -6,7 +6,7 @@ zend.enable_gc=1 attach($s); +$s->offsetSet($s); gc_collect_cycles(); echo "ok"; ?> diff --git a/ext/spl/tests/SplObjectStorage/bug70365.phpt b/ext/spl/tests/SplObjectStorage/bug70365.phpt index 55ff58c9e9122..5e2ff3328ac3a 100644 --- a/ext/spl/tests/SplObjectStorage/bug70365.phpt +++ b/ext/spl/tests/SplObjectStorage/bug70365.phpt @@ -34,6 +34,7 @@ function ptr2str($ptr) } ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d array(5) { [0]=> int(1) diff --git a/ext/spl/tests/gh14639.phpt b/ext/spl/tests/SplObjectStorage/gh14639.phpt similarity index 94% rename from ext/spl/tests/gh14639.phpt rename to ext/spl/tests/SplObjectStorage/gh14639.phpt index 1b6f621d27bd3..41260855b2523 100644 --- a/ext/spl/tests/gh14639.phpt +++ b/ext/spl/tests/SplObjectStorage/gh14639.phpt @@ -14,7 +14,7 @@ $b = new SplObjectStorage(); for ($i = 10000; $i > 0; $i--) { $object = new StdClass(); $object->a = str_repeat("a", 2); - $b->attach($object); + $b->offsetSet($object); } ?> --EXPECTF-- diff --git a/ext/spl/tests/observer_001.phpt b/ext/spl/tests/SplObjectStorage/observer_001.phpt similarity index 100% rename from ext/spl/tests/observer_001.phpt rename to ext/spl/tests/SplObjectStorage/observer_001.phpt diff --git a/ext/spl/tests/observer_002.phpt b/ext/spl/tests/SplObjectStorage/observer_002.phpt similarity index 96% rename from ext/spl/tests/observer_002.phpt rename to ext/spl/tests/SplObjectStorage/observer_002.phpt index 74bf3d4b930b1..227122b637dea 100644 --- a/ext/spl/tests/observer_002.phpt +++ b/ext/spl/tests/SplObjectStorage/observer_002.phpt @@ -70,13 +70,13 @@ class SubjectImpl implements SplSubject function attach(SplObserver $observer): void { echo $this->name . '->' . __METHOD__ . '(' . $observer->getName() . ");\n"; - $this->observers->attach($observer); + $this->observers->offsetSet($observer); } function detach(SplObserver $observer): void { echo $this->name . '->' . __METHOD__ . '(' . $observer->getName() . ");\n"; - $this->observers->detach($observer); + $this->observers->offsetUnset($observer); } function count(): int @@ -100,7 +100,7 @@ class SubjectImpl implements SplSubject function contains($obj) { - return $this->observers->contains($obj); + return $this->observers->offsetExists($obj); } } diff --git a/ext/spl/tests/observer_003.phpt b/ext/spl/tests/SplObjectStorage/observer_003.phpt similarity index 93% rename from ext/spl/tests/observer_003.phpt rename to ext/spl/tests/SplObjectStorage/observer_003.phpt index 36ead9233658b..7708c526f947e 100644 --- a/ext/spl/tests/observer_003.phpt +++ b/ext/spl/tests/SplObjectStorage/observer_003.phpt @@ -17,7 +17,7 @@ $storage = new SplObjectStorage(); foreach(array(1,"2","foo",true) as $value) { - $storage->attach(new TestClass($value)); + $storage->offsetSet(new TestClass($value)); } var_dump(count($storage)); diff --git a/ext/spl/tests/observer_004.phpt b/ext/spl/tests/SplObjectStorage/observer_004.phpt similarity index 97% rename from ext/spl/tests/observer_004.phpt rename to ext/spl/tests/SplObjectStorage/observer_004.phpt index b0b25ec117a7d..96d2e5b999989 100644 --- a/ext/spl/tests/observer_004.phpt +++ b/ext/spl/tests/SplObjectStorage/observer_004.phpt @@ -27,7 +27,7 @@ $storage = new MyStorage(); foreach(array(1,2) as $value) { - $storage->attach(new TestClass($value)); + $storage->offsetSet(new TestClass($value)); } var_dump(count($storage)); diff --git a/ext/spl/tests/observer_005.phpt b/ext/spl/tests/SplObjectStorage/observer_005.phpt similarity index 97% rename from ext/spl/tests/observer_005.phpt rename to ext/spl/tests/SplObjectStorage/observer_005.phpt index 833b978d72527..b5b3669b870aa 100644 --- a/ext/spl/tests/observer_005.phpt +++ b/ext/spl/tests/SplObjectStorage/observer_005.phpt @@ -45,7 +45,7 @@ $storage = new MyStorage(1,2,3); foreach(array(array(4,5,6),array(7,8,9)) as $value) { - $storage->attach(new TestClass($value[0], $value[1], $value[2])); + $storage->offsetSet(new TestClass($value[0], $value[1], $value[2])); } var_dump(count($storage)); diff --git a/ext/spl/tests/observer_006.phpt b/ext/spl/tests/SplObjectStorage/observer_006.phpt similarity index 95% rename from ext/spl/tests/observer_006.phpt rename to ext/spl/tests/SplObjectStorage/observer_006.phpt index d1e535227970a..afd40e9b122a2 100644 --- a/ext/spl/tests/observer_006.phpt +++ b/ext/spl/tests/SplObjectStorage/observer_006.phpt @@ -27,7 +27,7 @@ $storage = new MyStorage(); foreach(array(1=>"foo",2=>42) as $key => $value) { - $storage->attach(new TestClass($key), $value); + $storage->offsetSet(new TestClass($key), $value); } var_dump(count($storage)); @@ -52,8 +52,8 @@ foreach($storage2 as $object) } var_dump($storage2); -$storage->attach(new TestClass(3), new stdClass); -$storage->attach(new TestClass(4), new TestClass(5)); +$storage->offsetSet(new TestClass(3), new stdClass); +$storage->offsetSet(new TestClass(4), new TestClass(5)); echo "===UNSERIALIZE2===\n"; var_dump(unserialize(serialize($storage))); $storage->rewind(); @@ -70,7 +70,7 @@ $storage->next(); $storage->next(); var_dump($storage->key()); var_dump($storage->current()); -$storage->attach($storage->current(), "replaced"); +$storage->offsetSet($storage->current(), "replaced"); echo "===UNSERIALIZE4===\n"; var_dump(unserialize(serialize($storage))); diff --git a/ext/spl/tests/observer_007.phpt b/ext/spl/tests/SplObjectStorage/observer_007.phpt similarity index 100% rename from ext/spl/tests/observer_007.phpt rename to ext/spl/tests/SplObjectStorage/observer_007.phpt diff --git a/ext/spl/tests/observer_008.phpt b/ext/spl/tests/SplObjectStorage/observer_008.phpt similarity index 71% rename from ext/spl/tests/observer_008.phpt rename to ext/spl/tests/SplObjectStorage/observer_008.phpt index 0f6f0d263b9e8..36769c57d5243 100644 --- a/ext/spl/tests/observer_008.phpt +++ b/ext/spl/tests/SplObjectStorage/observer_008.phpt @@ -9,24 +9,24 @@ $o2 = new StdClass; $o3 = new StdClass; $a = new A; -$a->attach($o1); -$a->attach($o2); +$a->offsetSet($o1); +$a->offsetSet($o2); $b = new SplObjectStorage(); -$b->attach($o2); -$b->attach($o3); +$b->offsetSet($o2); +$b->offsetSet($o3); -$a->addAll($b); +$a->offsetUnset($b); var_dump($a->count()); -$a->detach($o3); +$a->offsetUnset($o3); var_dump($a->count()); $a->removeAll($b); var_dump($a->count()); ?> --EXPECT-- -int(3) +int(2) int(2) int(1) diff --git a/ext/spl/tests/observer_009.phpt b/ext/spl/tests/SplObjectStorage/observer_009.phpt similarity index 87% rename from ext/spl/tests/observer_009.phpt rename to ext/spl/tests/SplObjectStorage/observer_009.phpt index 58f49980846ba..0b402c1d31e00 100644 --- a/ext/spl/tests/observer_009.phpt +++ b/ext/spl/tests/SplObjectStorage/observer_009.phpt @@ -5,8 +5,8 @@ SPL: SplObjectStorage addAll/removeAll class Foo {} $storageA = new \SplObjectStorage(); -$storageA->attach(new \Foo); -$storageA->attach(new \Foo); +$storageA->offsetSet(new \Foo); +$storageA->offsetSet(new \Foo); echo ("Count storage A: " . count($storageA)); foreach ($storageA as $object) { diff --git a/ext/spl/tests/observer_010.phpt b/ext/spl/tests/SplObjectStorage/observer_010.phpt similarity index 100% rename from ext/spl/tests/observer_010.phpt rename to ext/spl/tests/SplObjectStorage/observer_010.phpt diff --git a/ext/spl/tests/arrayObject_getFlags_basic1.phpt b/ext/spl/tests/arrayObject_getFlags_basic1.phpt deleted file mode 100644 index 612a753680a38..0000000000000 --- a/ext/spl/tests/arrayObject_getFlags_basic1.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -SPL: ArrayObject::getFlags() basic usage ---FILE-- -getFlags()); - -$ao = new ArrayObject(new ArrayObject(array(1,2,3)), ArrayObject::STD_PROP_LIST); -var_dump($ao->getFlags()); - -$ao = new ArrayObject(new ArrayIterator(new ArrayObject()), ArrayObject::ARRAY_AS_PROPS); -var_dump($ao->getFlags()); - -$ao = new ArrayObject(new ArrayObject(), ArrayObject::STD_PROP_LIST|ArrayObject::ARRAY_AS_PROPS); -var_dump($ao->getFlags()); - -$cao = clone $ao; -var_dump($cao->getFlags()); -?> ---EXPECT-- -int(0) -int(1) -int(2) -int(3) -int(3) diff --git a/ext/spl/tests/arrayObject_getFlags_basic2.phpt b/ext/spl/tests/arrayObject_getFlags_basic2.phpt deleted file mode 100644 index db44322d674fa..0000000000000 --- a/ext/spl/tests/arrayObject_getFlags_basic2.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -SPL: ArrayObject::getFlags() - ensure flags are passed on to nested array objects and iterators. ---FILE-- -getFlags()); - -$ao2 = new ArrayObject($ao); -var_dump($ao2->getFlags()); -var_dump($ao2->getIterator()->getFlags()); - -$ai = new ArrayIterator($ao); -var_dump($ai->getFlags()); - -$ao2 = new ArrayObject($ao, 0); -var_dump($ao2->getFlags()); - -?> ---EXPECT-- -int(3) -int(3) -int(3) -int(3) -int(0) diff --git a/ext/spl/tests/bug62978.phpt b/ext/spl/tests/bug62978.phpt index 758649e231692..5c5ca05d366ba 100644 --- a/ext/spl/tests/bug62978.phpt +++ b/ext/spl/tests/bug62978.phpt @@ -26,6 +26,8 @@ var_dump($a[$fp]); fclose($fp); ?> --EXPECTF-- +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d + Warning: Undefined array key "epic_magic" in %s on line %d NULL diff --git a/ext/spl/tests/bug69845.phpt b/ext/spl/tests/bug69845.phpt deleted file mode 100644 index 09c9f2356d44a..0000000000000 --- a/ext/spl/tests/bug69845.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Fixed bug #69845 (ArrayObject with ARRAY_AS_PROPS broken) ---FILE-- -itemType = 'bulletin'; - var_dump(!is_null($data['itemType'])); -} -?> ---EXPECT-- -bool(true) -bool(true) diff --git a/ext/spl/tests/bug70366.phpt b/ext/spl/tests/bug70366.phpt index d3d3317bff370..955dea18e11b3 100644 --- a/ext/spl/tests/bug70366.phpt +++ b/ext/spl/tests/bug70366.phpt @@ -34,6 +34,7 @@ function ptr2str($ptr) } ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d array(5) { [0]=> int(1) diff --git a/ext/spl/tests/bug70852.phpt b/ext/spl/tests/bug70852.phpt index 44168f990320a..008a7c0ca4af1 100644 --- a/ext/spl/tests/bug70852.phpt +++ b/ext/spl/tests/bug70852.phpt @@ -8,8 +8,12 @@ var_dump($y[NULL]); var_dump($y[NULL]++); ?> --EXPECTF-- +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d + Warning: Undefined array key "" in %s on line %d NULL +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d + Warning: Undefined array key "" in %s on line %d NULL diff --git a/ext/spl/tests/bug71204.phpt b/ext/spl/tests/bug71204.phpt index 8d1c721c100b7..3669597a08448 100644 --- a/ext/spl/tests/bug71204.phpt +++ b/ext/spl/tests/bug71204.phpt @@ -13,6 +13,8 @@ spl_autoload_register(function ($name) { new A(); ?> --EXPECTF-- +Deprecated: spl_autoload_unregister(): Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated, to remove all registered autoloaders, call spl_autoload_unregister() for all values returned from spl_autoload_functions() in %s on line %d + Fatal error: Uncaught Error: Class "A" not found in %s:%d Stack trace: #0 {main} diff --git a/ext/spl/tests/gh19094.phpt b/ext/spl/tests/gh19094.phpt new file mode 100644 index 0000000000000..d0665c3e8f067 --- /dev/null +++ b/ext/spl/tests/gh19094.phpt @@ -0,0 +1,56 @@ +--TEST-- +GH-19094 (Attaching class with no Iterator implementation to MultipleIterator causes crash) +--FILE-- +getMessage(), "\n"; +} +try { + $cls[new MyAggregate] = 1; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +$cls[new MyIterator] = 1; +try { + $cls->key(); +} catch (RuntimeException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Can only attach objects that implement the Iterator interface +Can only attach objects that implement the Iterator interface +Called key() with non valid sub iterator diff --git a/ext/spl/tests/gh19577.phpt b/ext/spl/tests/gh19577.phpt new file mode 100644 index 0000000000000..641cfa57e0651 --- /dev/null +++ b/ext/spl/tests/gh19577.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-19577: Integer overflow in LimitIterator with small offset and PHP_INT_MAX count +--FILE-- + 'A', 1 => 'B', 2 => 'C', 3 => 'D')); +$it = new LimitIterator($it, 2, PHP_INT_MAX); + +foreach($it as $val => $key) { + echo "Key: $val, Value: $key\n"; +} + +?> +--EXPECT-- +Key: 2, Value: C +Key: 3, Value: D diff --git a/ext/spl/tests/iterator_016.phpt b/ext/spl/tests/iterator_016.phpt index abc81c165ae66..33ee78064201c 100644 --- a/ext/spl/tests/iterator_016.phpt +++ b/ext/spl/tests/iterator_016.phpt @@ -8,7 +8,7 @@ class Menu extends ArrayObject function getIterator(): RecursiveArrayIterator { echo __METHOD__ . "\n"; - return new RecursiveArrayIterator($this); + return new RecursiveArrayIterator($this->getArrayCopy()); } } @@ -42,7 +42,18 @@ class MenuOutput extends RecursiveIteratorIterator } } -$arr = array("a", array("ba", array("bba", "bbb"), array(array("bcaa"))), array("ca"), "d"); +$arr = [ + "a", + [ + "ba", + ["bba", "bbb"], + [ + ["bcaa"] + ] + ], + ["ca"], + "d", +]; $obj = new Menu($arr); $rit = new MenuOutput($obj); foreach($rit as $k=>$v) diff --git a/ext/spl/tests/iterator_069.phpt b/ext/spl/tests/iterator_069.phpt index b9ee3f4b820d9..e30251fa9162f 100644 --- a/ext/spl/tests/iterator_069.phpt +++ b/ext/spl/tests/iterator_069.phpt @@ -3,10 +3,10 @@ SPL: RecursiveIteratorIterator cannot be used with foreach by reference --FILE-- getIterator()); +$recArrIt = new RecursiveArrayIterator([ + [1, 2], + ['a', 'b'], +]); $recItIt = new RecursiveIteratorIterator($recArrIt); diff --git a/ext/spl/tests/iterator_071.phpt b/ext/spl/tests/iterator_071.phpt index 7f525eb2c61d6..4f9b18d0c0748 100644 --- a/ext/spl/tests/iterator_071.phpt +++ b/ext/spl/tests/iterator_071.phpt @@ -3,10 +3,10 @@ SPL: RecursiveIteratorIterator - Test where the case is RS_SELF and mode is CHIL --FILE-- getIterator()); +$recArrIt = new RecursiveArrayIterator([ + [1, 2], + ['a', 'b'], +]); class MyRecursiveIteratorIterator extends RecursiveIteratorIterator { @@ -29,4 +29,8 @@ MyRecursiveIteratorIterator::nextelement MyRecursiveIteratorIterator::nextelement 0 MyRecursiveIteratorIterator::nextelement +0 +MyRecursiveIteratorIterator::nextelement +1 +MyRecursiveIteratorIterator::nextelement 1 diff --git a/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt b/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt index 6a7d3eb8a514c..76bacc3615f7d 100644 --- a/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_beginchildren_error.phpt @@ -3,10 +3,10 @@ SPL: RecursiveIteratorIterator - Exception thrown in beginchildren which should --FILE-- getIterator()); +$recArrIt = new RecursiveArrayIterator([ + [1, 2], + ['a', 'b'], +]); class MyRecursiveIteratorIterator extends RecursiveIteratorIterator { diff --git a/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt b/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt index 1c96ee9fcd0bf..9256e9e3b1b27 100644 --- a/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_callHasChildren_error.phpt @@ -3,10 +3,10 @@ SPL: RecursiveIteratorIterator - Exception thrown in callHasChildren which shoul --FILE-- getIterator()); +$recArrIt = new RecursiveArrayIterator([ + [1, 2], + ['a', 'b'], +]); class MyRecursiveIteratorIterator extends RecursiveIteratorIterator { diff --git a/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt b/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt index 13af7ce01986d..07dee9c4acbbc 100644 --- a/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_endchildren_error.phpt @@ -3,10 +3,10 @@ SPL: RecursiveIteratorIterator - Exception thrown in endchildren which should be --FILE-- getIterator()); +$recArrIt = new RecursiveArrayIterator([ + [1, 2], + ['a', 'b'], +]); class MyRecursiveIteratorIterator extends RecursiveIteratorIterator { @@ -30,6 +30,8 @@ foreach ($recItIt2 as $val) echo "$val\n"; --EXPECTF-- 1 2 +a +b ===NEXT LOOP=== 1 2 diff --git a/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt b/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt index d92d309c754ba..f89f47e849b25 100644 --- a/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt +++ b/ext/spl/tests/recursiveIteratorIterator_nextelement_error.phpt @@ -3,10 +3,10 @@ SPL: RecursiveIteratorIterator - Exception thrown in nextelement which should be --FILE-- getIterator()); +$recArrIt = new RecursiveArrayIterator([ + [1, 2], + ['a', 'b'], +]); class MyRecursiveIteratorIterator extends RecursiveIteratorIterator { diff --git a/ext/spl/tests/recursive_tree_iterator_005.phpt b/ext/spl/tests/recursive_tree_iterator_005.phpt deleted file mode 100644 index a63b26685c561..0000000000000 --- a/ext/spl/tests/recursive_tree_iterator_005.phpt +++ /dev/null @@ -1,114 +0,0 @@ ---TEST-- -SPL: RecursiveTreeIterator and binary vs unicode (PHP 6.0+) ---INI-- -error_reporting=E_ALL&~E_NOTICE ---FILE-- - array( - (binary) "binary", - "abc2", - 1, - ), - (binary) "binary" => array( - 2, - "b", - 3 => array( - 4, - "c", - ), - "4abc" => array( - 4, - "c", - ), - ), -); - -$it = new RecursiveTreeIterator(new RecursiveArrayIterator($ary), 0); -foreach($it as $k => $v) { - var_dump($v); -} -echo "\n----------------\n\n"; -foreach($it as $k => $v) { - var_dump($k); -} -echo "\n----------------\n\n"; -echo "key, getEntry, current:\n"; -foreach($it as $k => $v) { - var_dump($it->key(), $it->getEntry(), $it->current()); -} -?> ---EXPECT-- -string(7) "|-Array" -string(10) "| |-binary" -string(8) "| |-abc2" -string(5) "| \-1" -string(7) "\-Array" -string(5) " |-2" -string(5) " |-b" -string(9) " |-Array" -string(7) " | |-4" -string(7) " | \-c" -string(9) " \-Array" -string(7) " |-4" -string(7) " \-c" - ----------------- - -string(3) "|-0" -string(5) "| |-0" -string(5) "| |-1" -string(5) "| \-2" -string(8) "\-binary" -string(5) " |-0" -string(5) " |-1" -string(5) " |-3" -string(7) " | |-0" -string(7) " | \-1" -string(8) " \-4abc" -string(7) " |-0" -string(7) " \-1" - ----------------- - -key, getEntry, current: -string(3) "|-0" -string(5) "Array" -string(7) "|-Array" -string(5) "| |-0" -string(6) "binary" -string(10) "| |-binary" -string(5) "| |-1" -string(4) "abc2" -string(8) "| |-abc2" -string(5) "| \-2" -string(1) "1" -string(5) "| \-1" -string(8) "\-binary" -string(5) "Array" -string(7) "\-Array" -string(5) " |-0" -string(1) "2" -string(5) " |-2" -string(5) " |-1" -string(1) "b" -string(5) " |-b" -string(5) " |-3" -string(5) "Array" -string(9) " |-Array" -string(7) " | |-0" -string(1) "4" -string(7) " | |-4" -string(7) " | \-1" -string(1) "c" -string(7) " | \-c" -string(8) " \-4abc" -string(5) "Array" -string(9) " \-Array" -string(7) " |-0" -string(1) "4" -string(7) " |-4" -string(7) " \-1" -string(1) "c" -string(7) " \-c" diff --git a/ext/spl/tests/recursive_tree_iterator_007.phpt b/ext/spl/tests/recursive_tree_iterator_007.phpt index 2907f39f26575..75f1e6386c8ee 100644 --- a/ext/spl/tests/recursive_tree_iterator_007.phpt +++ b/ext/spl/tests/recursive_tree_iterator_007.phpt @@ -1,15 +1,16 @@ --TEST-- SPL: RecursiveTreeIterator and Exception from getEntry() ---INI-- -error_reporting=E_ALL&~E_NOTICE --FILE-- it = new RecursiveArrayIterator($it); } function getIterator(): Traversable { @@ -27,5 +28,10 @@ try { } ?> ---EXPECT-- +--EXPECTF-- +[0] => |-Array +[0] => | \-string +[1] => \-Array + +Deprecated: ArrayIterator::__construct(): Using an object as a backing array for ArrayIterator is deprecated, as it allows violating class constraints and invariants in %s on line %d Object of class stdClass could not be converted to string diff --git a/ext/spl/tests/spl_autoload_002.phpt b/ext/spl/tests/spl_autoload_002.phpt index 1a67baabd0b3c..2739e56e3bed1 100644 --- a/ext/spl/tests/spl_autoload_002.phpt +++ b/ext/spl/tests/spl_autoload_002.phpt @@ -35,7 +35,7 @@ spl_autoload_unregister('spl_autoload'); var_dump(spl_autoload_functions()); ?> ---EXPECT-- +--EXPECTF-- array(0) { } array(1) { @@ -56,6 +56,8 @@ array(2) { [1]=> string(16) "SplAutoloadTest2" } + +Deprecated: spl_autoload_unregister(): Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated, to remove all registered autoloaders, call spl_autoload_unregister() for all values returned from spl_autoload_functions() in %s on line %d array(0) { } array(1) { diff --git a/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt b/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt index 0a7ca5a1352fd..867a67e6eb526 100644 --- a/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt +++ b/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt @@ -5,6 +5,8 @@ spl_autoload_unregister("spl_autoload_call") without registrations var_dump(spl_autoload_unregister("spl_autoload_call")); ?> Done ---EXPECT-- +--EXPECTF-- + +Deprecated: spl_autoload_unregister(): Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated, to remove all registered autoloaders, call spl_autoload_unregister() for all values returned from spl_autoload_functions() in %s on line %d bool(true) Done diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 5e402300980bb..21b6840a8d1b2 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -1987,6 +1987,16 @@ PHP_METHOD(SQLite3Result, columnType) } /* }}} */ +static void sqlite3result_fill_column_names_cache(php_sqlite3_result *result_obj, int nb_cols) +{ + result_obj->column_names = safe_emalloc(nb_cols, sizeof(zend_string*), 0); + + for (int i = 0; i < nb_cols; i++) { + const char *column = sqlite3_column_name(result_obj->stmt_obj->stmt, i); + result_obj->column_names[i] = zend_string_init(column, strlen(column), 0); + } +} + /* {{{ Fetch a result row as both an associative or numerically indexed array or both. */ PHP_METHOD(SQLite3Result, fetchArray) { @@ -2019,12 +2029,7 @@ PHP_METHOD(SQLite3Result, fetchArray) /* Cache column names to speed up repeated fetchArray calls. */ if (mode & PHP_SQLITE3_ASSOC && !result_obj->column_names) { - result_obj->column_names = emalloc(n_cols * sizeof(zend_string*)); - - for (int i = 0; i < n_cols; i++) { - const char *column = sqlite3_column_name(result_obj->stmt_obj->stmt, i); - result_obj->column_names[i] = zend_string_init(column, strlen(column), 0); - } + sqlite3result_fill_column_names_cache(result_obj, n_cols); } array_init(return_value); @@ -2056,7 +2061,7 @@ static void sqlite3result_clear_column_names_cache(php_sqlite3_result *result) { PHP_METHOD(SQLite3Result, fetchAll) { - int i, nb_cols; + int nb_cols; bool done = false; php_sqlite3_result *result_obj; zval *object = ZEND_THIS; @@ -2071,14 +2076,8 @@ PHP_METHOD(SQLite3Result, fetchAll) SQLITE3_CHECK_INITIALIZED(result_obj->db_obj, result_obj->stmt_obj->initialised, SQLite3Result) nb_cols = sqlite3_column_count(result_obj->stmt_obj->stmt); - if (mode & PHP_SQLITE3_ASSOC) { - sqlite3result_clear_column_names_cache(result_obj); - result_obj->column_names = emalloc(nb_cols * sizeof(zend_string*)); - - for (i = 0; i < nb_cols; i++) { - const char *column = sqlite3_column_name(result_obj->stmt_obj->stmt, i); - result_obj->column_names[i] = zend_string_init(column, strlen(column), 0); - } + if (mode & PHP_SQLITE3_ASSOC && !result_obj->column_names) { + sqlite3result_fill_column_names_cache(result_obj, nb_cols); } result_obj->column_count = nb_cols; array_init(return_value); @@ -2479,9 +2478,7 @@ static zend_always_inline void php_sqlite3_fetch_one(int n_cols, php_sqlite3_res if (mode & PHP_SQLITE3_ASSOC) { if (mode & PHP_SQLITE3_NUM) { - if (Z_REFCOUNTED(data)) { - Z_ADDREF(data); - } + Z_TRY_ADDREF(data); } /* Note: we can't use the "add_new" variant here instead of "update" because * when the same column name is encountered, the last result should be taken. */ diff --git a/ext/sqlite3/tests/sqlite3_explain.phpt b/ext/sqlite3/tests/sqlite3_explain.phpt index f580783ca1d14..40648588733c6 100644 --- a/ext/sqlite3/tests/sqlite3_explain.phpt +++ b/ext/sqlite3/tests/sqlite3_explain.phpt @@ -79,7 +79,7 @@ array(%d) { ["addr"]=> int(1) ["opcode"]=> - string(13) "InitCoroutine" + string(%d) "%s" ["p1"]=> int(3) ["p2"]=> @@ -87,7 +87,7 @@ array(%d) { ["p3"]=> int(2) ["p4"]=> - NULL + %s ["p5"]=> int(0) ["comment"]=> @@ -368,7 +368,7 @@ array(1) { ["parent"]=> int(0) ["notused"]=> - int(0) + int(%d) ["detail"]=> string(17) "SCAN test_explain" } diff --git a/ext/standard/array.c b/ext/standard/array.c index 522e7f715acb7..96795e623cb9e 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3318,6 +3318,9 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H zval *entry; /* Hash entry */ uint32_t iter_pos = zend_hash_iterators_lower_pos(in_hash, 0); + GC_ADDREF(in_hash); + HT_ALLOW_COW_VIOLATION(in_hash); /* Will be reset when setting the flags for in_hash */ + /* Get number of entries in the input hash */ num_in = zend_hash_num_elements(in_hash); @@ -3485,6 +3488,15 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H HT_SET_ITERATORS_COUNT(&out_hash, HT_ITERATORS_COUNT(in_hash)); HT_SET_ITERATORS_COUNT(in_hash, 0); in_hash->pDestructor = NULL; + + if (UNEXPECTED(GC_DELREF(in_hash) == 0)) { + /* Array was completely deallocated during the operation */ + zend_array_destroy(in_hash); + zend_hash_destroy(&out_hash); + zend_throw_error(NULL, "Array was modified during array_splice operation"); + return; + } + zend_hash_destroy(in_hash); HT_FLAGS(in_hash) = HT_FLAGS(&out_hash); @@ -6051,7 +6063,7 @@ PHP_FUNCTION(array_multisort) for (i = 0; i < MULTISORT_LAST; i++) { parse_state[i] = 0; } - func = ARRAYG(multisort_func) = ecalloc(argc, sizeof(bucket_compare_func_t)); + func = ecalloc(argc, sizeof(bucket_compare_func_t)); /* Here we go through the input arguments and parse them. Each one can * be either an array or a sort flag which follows an array. If not @@ -6067,7 +6079,7 @@ PHP_FUNCTION(array_multisort) /* We see the next array, so we update the sort flags of * the previous array and reset the sort flags. */ if (i > 0) { - ARRAYG(multisort_func)[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC); + func[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC); sort_order = PHP_SORT_ASC; sort_type = PHP_SORT_REGULAR; } @@ -6119,8 +6131,6 @@ PHP_FUNCTION(array_multisort) MULTISORT_ABORT; } } - /* Take care of the last array sort flags. */ - ARRAYG(multisort_func)[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC); /* Make sure the arrays are of the same size. */ array_size = zend_hash_num_elements(Z_ARRVAL_P(arrays[0])); @@ -6138,6 +6148,11 @@ PHP_FUNCTION(array_multisort) RETURN_TRUE; } + /* Take care of the last array sort flags. */ + func[num_arrays - 1] = php_get_data_compare_func_unstable(sort_type, sort_order != PHP_SORT_ASC); + bucket_compare_func_t *old_multisort_func = ARRAYG(multisort_func); + ARRAYG(multisort_func) = func; + /* Create the indirection array. This array is of size MxN, where * M is the number of entries in each input array and N is the number * of the input arrays + 1. The last column is UNDEF to indicate the end @@ -6214,6 +6229,7 @@ PHP_FUNCTION(array_multisort) efree(indirect); efree(func); efree(arrays); + ARRAYG(multisort_func) = old_multisort_func; } /* }}} */ @@ -6965,6 +6981,7 @@ PHP_FUNCTION(array_key_exists) RETVAL_BOOL(zend_hash_index_exists(ht, Z_LVAL_P(key))); break; case IS_NULL: + zend_error(E_DEPRECATED, "Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead"); RETVAL_BOOL(zend_hash_exists(ht, ZSTR_EMPTY_ALLOC())); break; case IS_DOUBLE: @@ -7023,6 +7040,7 @@ PHP_FUNCTION(array_chunk) } array_init_size(return_value, (uint32_t)(((num_in - 1) / size) + 1)); + zend_hash_real_init_packed(Z_ARRVAL_P(return_value)); ZVAL_UNDEF(&chunk); @@ -7046,9 +7064,10 @@ PHP_FUNCTION(array_chunk) /* If reached the chunk size, add it to the result array, and reset the * pointer. */ - if (!(++current % size)) { + if (++current == size) { add_next_index_zval(return_value, &chunk); ZVAL_UNDEF(&chunk); + current = 0; } } ZEND_HASH_FOREACH_END(); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index f26bef3daa4e7..aa5c2a2cedfff 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -141,6 +141,7 @@ static void user_shutdown_function_dtor(zval *zv); static void user_tick_function_dtor(user_tick_function_entry *tick_function_entry); static const zend_module_dep standard_deps[] = { /* {{{ */ + ZEND_MOD_REQUIRED("uri") ZEND_MOD_OPTIONAL("session") ZEND_MOD_END }; @@ -299,11 +300,11 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */ BASIC_MINIT_SUBMODULE(var) BASIC_MINIT_SUBMODULE(file) - BASIC_MINIT_SUBMODULE(pack) BASIC_MINIT_SUBMODULE(browscap) BASIC_MINIT_SUBMODULE(standard_filters) BASIC_MINIT_SUBMODULE(user_filters) BASIC_MINIT_SUBMODULE(password) + BASIC_MINIT_SUBMODULE(image) #ifdef ZTS BASIC_MINIT_SUBMODULE(localeconv) @@ -377,6 +378,7 @@ PHP_MSHUTDOWN_FUNCTION(basic) /* {{{ */ #endif BASIC_MSHUTDOWN_SUBMODULE(crypt) BASIC_MSHUTDOWN_SUBMODULE(password) + BASIC_MSHUTDOWN_SUBMODULE(image) return SUCCESS; } diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 09f63860f1163..7913ca0e00194 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -124,33 +124,33 @@ /** * @var int - * @deprecated * @cvalue PHP_ASSERT_ACTIVE */ +#[\Deprecated(since: '8.3', message: 'as assert_options() is deprecated')] const ASSERT_ACTIVE = UNKNOWN; /** * @var int - * @deprecated * @cvalue PHP_ASSERT_CALLBACK */ +#[\Deprecated(since: '8.3', message: 'as assert_options() is deprecated')] const ASSERT_CALLBACK = UNKNOWN; /** * @var int - * @deprecated * @cvalue PHP_ASSERT_BAIL */ +#[\Deprecated(since: '8.3', message: 'as assert_options() is deprecated')] const ASSERT_BAIL = UNKNOWN; /** * @var int - * @deprecated * @cvalue PHP_ASSERT_WARNING */ +#[\Deprecated(since: '8.3', message: 'as assert_options() is deprecated')] const ASSERT_WARNING = UNKNOWN; /** * @var int - * @deprecated * @cvalue PHP_ASSERT_EXCEPTION */ +#[\Deprecated(since: '8.3', message: 'as assert_options() is deprecated')] const ASSERT_EXCEPTION = UNKNOWN; /* basic_functions.h */ @@ -260,87 +260,70 @@ const PHP_QUERY_RFC3986 = UNKNOWN; /** - * @var float * @cvalue M_E */ const M_E = 2.718281828459045; /** - * @var float * @cvalue M_LOG2E */ const M_LOG2E = 1.4426950408889634074; /** - * @var float * @cvalue M_LOG10E */ const M_LOG10E = 0.43429448190325182765; /** - * @var float * @cvalue M_LN2 */ const M_LN2 = 0.69314718055994530942; /** - * @var float * @cvalue M_LN10 */ const M_LN10 = 2.30258509299404568402; /** - * @var float * @cvalue M_PI */ const M_PI = 3.14159265358979323846; /** - * @var float * @cvalue M_PI_2 */ const M_PI_2 = 1.57079632679489661923; /** - * @var float * @cvalue M_PI_4 */ const M_PI_4 = 0.78539816339744830962; /** - * @var float * @cvalue M_1_PI */ const M_1_PI = 0.31830988618379067154; /** - * @var float * @cvalue M_2_PI */ const M_2_PI = 0.63661977236758134308; /** - * @var float * @cvalue M_SQRTPI */ const M_SQRTPI = 1.77245385090551602729; /** - * @var float * @cvalue M_2_SQRTPI */ const M_2_SQRTPI = 1.12837916709551257390; /** - * @var float * @cvalue M_LNPI */ const M_LNPI = 1.14472988584940017414; /** - * @var float * @cvalue M_EULER */ const M_EULER = 0.57721566490153286061; /** - * @var float * @cvalue M_SQRT2 */ const M_SQRT2 = 1.41421356237309504880; /** - * @var float * @cvalue M_SQRT1_2 */ const M_SQRT1_2 = 0.70710678118654752440; /** - * @var float * @cvalue M_SQRT3 */ const M_SQRT3 = 1.73205080756887729352; @@ -383,17 +366,11 @@ * @cvalue PHP_MAX_SALT_LEN */ const CRYPT_SALT_LENGTH = UNKNOWN; -/** @var int */ const CRYPT_STD_DES = 1; -/** @var int */ const CRYPT_EXT_DES = 1; -/** @var int */ const CRYPT_MD5 = 1; -/** @var int */ const CRYPT_BLOWFISH = 1; -/** @var int */ const CRYPT_SHA256 = 1; -/** @var int */ const CRYPT_SHA512 = 1; /* dns.c */ @@ -646,6 +623,11 @@ * @cvalue IMAGE_FILETYPE_AVIF */ const IMAGETYPE_AVIF = UNKNOWN; +/** + * @var int + * @cvalue IMAGE_FILETYPE_HEIF + */ +const IMAGETYPE_HEIF = UNKNOWN; /** * @var int * @cvalue IMAGE_FILETYPE_UNKNOWN @@ -653,7 +635,7 @@ const IMAGETYPE_UNKNOWN = UNKNOWN; /** * @var int - * @cvalue IMAGE_FILETYPE_COUNT + * @cvalue IMAGE_FILETYPE_FIXED_COUNT */ const IMAGETYPE_COUNT = UNKNOWN; @@ -1686,13 +1668,11 @@ function array_merge_recursive(array ...$arrays): array {} /** * @compile-time-eval - * @refcount 1 */ function array_replace(array $array, array ...$replacements): array {} /** * @compile-time-eval - * @refcount 1 */ function array_replace_recursive(array $array, array ...$replacements): array {} @@ -1775,19 +1755,16 @@ function array_intersect_key(array $array, array ...$arrays): array {} /** * @param array|callable $rest - * @refcount 1 */ function array_intersect_ukey(array $array, ...$rest): array {} /** * @compile-time-eval - * @refcount 1 */ function array_intersect(array $array, array ...$arrays): array {} /** * @param array|callable $rest - * @refcount 1 */ function array_uintersect(array $array, ...$rest): array {} @@ -1805,13 +1782,11 @@ function array_uintersect_assoc(array $array, ...$rest): array {} /** * @param array|callable $rest - * @refcount 1 */ function array_intersect_uassoc(array $array, ...$rest): array {} /** * @param array|callable $rest - * @refcount 1 */ function array_uintersect_uassoc(array $array, ...$rest): array {} @@ -2562,8 +2537,8 @@ function nl2br(string $string, bool $use_xhtml = true): string {} function strip_tags(string $string, array|string|null $allowed_tags = null): string {} /** - * @param array|string $locales - * @param string $rest + * @param array|string|null $locales + * @param string|null $rest */ function setlocale(int $category, $locales, ...$rest): string|false {} @@ -2699,7 +2674,6 @@ function scandir(string $directory, int $sorting_order = SCANDIR_SORT_ASCENDING, /** * @return array|false - * @refcount 1 */ function glob(string $pattern, int $flags = 0): array|false {} @@ -3589,6 +3563,7 @@ function stream_set_timeout($stream, int $seconds, int $microseconds = 0): bool * @param resource $stream * @alias stream_set_timeout */ +#[\Deprecated(since: '8.5', message: "use stream_set_timeout() instead")] function socket_set_timeout($stream, int $seconds, int $microseconds = 0): bool {} #endif diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 37df4de7bdfcd..668eca9aadc20 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: dfd7d2cfd31312f7f6c5074c10cab54e9d1fbccc */ + * Stub hash: f6bf6cdd07080c01d3a0cb08d71409d05b1084f9 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -3431,7 +3431,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(stream_set_chunk_size, arginfo_stream_set_chunk_size) #if (defined(HAVE_SYS_TIME_H) || defined(PHP_WIN32)) ZEND_FE(stream_set_timeout, arginfo_stream_set_timeout) - ZEND_RAW_FENTRY("socket_set_timeout", zif_stream_set_timeout, arginfo_socket_set_timeout, 0, NULL, NULL) + ZEND_RAW_FENTRY("socket_set_timeout", zif_stream_set_timeout, arginfo_socket_set_timeout, ZEND_ACC_DEPRECATED, NULL, NULL) #endif ZEND_RAW_FENTRY("gettype", zif_gettype, arginfo_gettype, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("get_debug_type", zif_get_debug_type, arginfo_get_debug_type, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) @@ -3518,11 +3518,11 @@ static void register_basic_functions_symbols(int module_number) REGISTER_LONG_CONSTANT("COUNT_RECURSIVE", PHP_COUNT_RECURSIVE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_BOTH", ARRAY_FILTER_USE_BOTH, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_KEY", ARRAY_FILTER_USE_KEY, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("ASSERT_ACTIVE", PHP_ASSERT_ACTIVE, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("ASSERT_CALLBACK", PHP_ASSERT_CALLBACK, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("ASSERT_BAIL", PHP_ASSERT_BAIL, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("ASSERT_WARNING", PHP_ASSERT_WARNING, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("ASSERT_EXCEPTION", PHP_ASSERT_EXCEPTION, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_ASSERT_ACTIVE = REGISTER_LONG_CONSTANT("ASSERT_ACTIVE", PHP_ASSERT_ACTIVE, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_ASSERT_CALLBACK = REGISTER_LONG_CONSTANT("ASSERT_CALLBACK", PHP_ASSERT_CALLBACK, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_ASSERT_BAIL = REGISTER_LONG_CONSTANT("ASSERT_BAIL", PHP_ASSERT_BAIL, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_ASSERT_WARNING = REGISTER_LONG_CONSTANT("ASSERT_WARNING", PHP_ASSERT_WARNING, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_ASSERT_EXCEPTION = REGISTER_LONG_CONSTANT("ASSERT_EXCEPTION", PHP_ASSERT_EXCEPTION, CONST_PERSISTENT | CONST_DEPRECATED); REGISTER_LONG_CONSTANT("CONNECTION_ABORTED", PHP_CONNECTION_ABORTED, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CONNECTION_NORMAL", PHP_CONNECTION_NORMAL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CONNECTION_TIMEOUT", PHP_CONNECTION_TIMEOUT, CONST_PERSISTENT); @@ -3645,8 +3645,9 @@ static void register_basic_functions_symbols(int module_number) REGISTER_LONG_CONSTANT("IMAGETYPE_ICO", IMAGE_FILETYPE_ICO, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_WEBP", IMAGE_FILETYPE_WEBP, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_AVIF", IMAGE_FILETYPE_AVIF, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMAGETYPE_HEIF", IMAGE_FILETYPE_HEIF, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_COUNT, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_FIXED_COUNT, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INFO_GENERAL", PHP_INFO_GENERAL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INFO_CREDITS", PHP_INFO_CREDITS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INFO_CONFIGURATION", PHP_INFO_CONFIGURATION, CONST_PERSISTENT); @@ -3894,52 +3895,73 @@ static void register_basic_functions_symbols(int module_number) #if defined(HAVE_STRPTIME) zend_attribute *attribute_Deprecated_func_strptime_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "strptime", sizeof("strptime") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_strptime_0_arg0; - zend_string *attribute_Deprecated_func_strptime_0_arg0_str = zend_string_init("8.2", strlen("8.2"), 1); - ZVAL_STR(&attribute_Deprecated_func_strptime_0_arg0, attribute_Deprecated_func_strptime_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_strptime_0->args[0].value, &attribute_Deprecated_func_strptime_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_strptime_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_2)); attribute_Deprecated_func_strptime_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_strptime_0_arg1; zend_string *attribute_Deprecated_func_strptime_0_arg1_str = zend_string_init("use date_parse_from_format() (for locale-independent parsing), or IntlDateFormatter::parse() (for locale-dependent parsing) instead", strlen("use date_parse_from_format() (for locale-independent parsing), or IntlDateFormatter::parse() (for locale-dependent parsing) instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_strptime_0_arg1, attribute_Deprecated_func_strptime_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_strptime_0->args[1].value, &attribute_Deprecated_func_strptime_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_strptime_0->args[1].value, attribute_Deprecated_func_strptime_0_arg1_str); attribute_Deprecated_func_strptime_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); #endif zend_attribute *attribute_Deprecated_func_assert_options_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "assert_options", sizeof("assert_options") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_assert_options_0_arg0; - zend_string *attribute_Deprecated_func_assert_options_0_arg0_str = zend_string_init("8.3", strlen("8.3"), 1); - ZVAL_STR(&attribute_Deprecated_func_assert_options_0_arg0, attribute_Deprecated_func_assert_options_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_assert_options_0->args[0].value, &attribute_Deprecated_func_assert_options_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_assert_options_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); attribute_Deprecated_func_assert_options_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_utf8_encode_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "utf8_encode", sizeof("utf8_encode") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_utf8_encode_0_arg0; - zend_string *attribute_Deprecated_func_utf8_encode_0_arg0_str = zend_string_init("8.2", strlen("8.2"), 1); - ZVAL_STR(&attribute_Deprecated_func_utf8_encode_0_arg0, attribute_Deprecated_func_utf8_encode_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_utf8_encode_0->args[0].value, &attribute_Deprecated_func_utf8_encode_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_utf8_encode_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_2)); attribute_Deprecated_func_utf8_encode_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_utf8_encode_0_arg1; zend_string *attribute_Deprecated_func_utf8_encode_0_arg1_str = zend_string_init("visit the php.net documentation for various alternatives", strlen("visit the php.net documentation for various alternatives"), 1); - ZVAL_STR(&attribute_Deprecated_func_utf8_encode_0_arg1, attribute_Deprecated_func_utf8_encode_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_utf8_encode_0->args[1].value, &attribute_Deprecated_func_utf8_encode_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_utf8_encode_0->args[1].value, attribute_Deprecated_func_utf8_encode_0_arg1_str); attribute_Deprecated_func_utf8_encode_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_utf8_decode_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "utf8_decode", sizeof("utf8_decode") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_utf8_decode_0_arg0; - zend_string *attribute_Deprecated_func_utf8_decode_0_arg0_str = zend_string_init("8.2", strlen("8.2"), 1); - ZVAL_STR(&attribute_Deprecated_func_utf8_decode_0_arg0, attribute_Deprecated_func_utf8_decode_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_utf8_decode_0->args[0].value, &attribute_Deprecated_func_utf8_decode_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_utf8_decode_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_2)); attribute_Deprecated_func_utf8_decode_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_utf8_decode_0_arg1; - zend_string *attribute_Deprecated_func_utf8_decode_0_arg1_str = zend_string_init("visit the php.net documentation for various alternatives", strlen("visit the php.net documentation for various alternatives"), 1); - ZVAL_STR(&attribute_Deprecated_func_utf8_decode_0_arg1, attribute_Deprecated_func_utf8_decode_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_utf8_decode_0->args[1].value, &attribute_Deprecated_func_utf8_decode_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_utf8_decode_0->args[1].value, attribute_Deprecated_func_utf8_encode_0_arg1_str); attribute_Deprecated_func_utf8_decode_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "password_hash", sizeof("password_hash") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "password_verify", sizeof("password_verify") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); +#if (defined(HAVE_SYS_TIME_H) || defined(PHP_WIN32)) + + zend_attribute *attribute_Deprecated_func_socket_set_timeout_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "socket_set_timeout", sizeof("socket_set_timeout") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_socket_set_timeout_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_socket_set_timeout_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_socket_set_timeout_0_arg1_str = zend_string_init("use stream_set_timeout() instead", strlen("use stream_set_timeout() instead"), 1); + ZVAL_STR(&attribute_Deprecated_func_socket_set_timeout_0->args[1].value, attribute_Deprecated_func_socket_set_timeout_0_arg1_str); + attribute_Deprecated_func_socket_set_timeout_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); +#endif + + zend_attribute *attribute_Deprecated_const_ASSERT_ACTIVE_0 = zend_add_global_constant_attribute(const_ASSERT_ACTIVE, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_ASSERT_ACTIVE_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); + attribute_Deprecated_const_ASSERT_ACTIVE_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1_str = zend_string_init("as assert_options() is deprecated", strlen("as assert_options() is deprecated"), 1); + ZVAL_STR(&attribute_Deprecated_const_ASSERT_ACTIVE_0->args[1].value, attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1_str); + attribute_Deprecated_const_ASSERT_ACTIVE_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_ASSERT_CALLBACK_0 = zend_add_global_constant_attribute(const_ASSERT_CALLBACK, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_ASSERT_CALLBACK_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); + attribute_Deprecated_const_ASSERT_CALLBACK_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_ASSERT_CALLBACK_0->args[1].value, attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1_str); + attribute_Deprecated_const_ASSERT_CALLBACK_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_ASSERT_BAIL_0 = zend_add_global_constant_attribute(const_ASSERT_BAIL, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_ASSERT_BAIL_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); + attribute_Deprecated_const_ASSERT_BAIL_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_ASSERT_BAIL_0->args[1].value, attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1_str); + attribute_Deprecated_const_ASSERT_BAIL_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_ASSERT_WARNING_0 = zend_add_global_constant_attribute(const_ASSERT_WARNING, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_ASSERT_WARNING_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); + attribute_Deprecated_const_ASSERT_WARNING_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_ASSERT_WARNING_0->args[1].value, attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1_str); + attribute_Deprecated_const_ASSERT_WARNING_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_ASSERT_EXCEPTION_0 = zend_add_global_constant_attribute(const_ASSERT_EXCEPTION, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_ASSERT_EXCEPTION_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); + attribute_Deprecated_const_ASSERT_EXCEPTION_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_ASSERT_EXCEPTION_0->args[1].value, attribute_Deprecated_const_ASSERT_ACTIVE_0_arg1_str); + attribute_Deprecated_const_ASSERT_EXCEPTION_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class___PHP_Incomplete_Class(void) diff --git a/ext/standard/dir.c b/ext/standard/dir.c index cced88e4ac8a5..918b92fab456f 100644 --- a/ext/standard/dir.c +++ b/ext/standard/dir.c @@ -160,6 +160,8 @@ PHP_FUNCTION(dir) static php_stream* php_dir_get_directory_stream_from_user_arg(php_stream *dir_stream) { if (dir_stream == NULL) { + php_error_docref(NULL, E_DEPRECATED, + "Passing null is deprecated, instead the last opened directory stream should be provided"); if (UNEXPECTED(DIRG(default_dir) == NULL)) { zend_type_error("No resource supplied"); return NULL; @@ -474,8 +476,7 @@ PHP_FUNCTION(glob) #ifdef PHP_GLOB_NOMATCH no_results: #endif - array_init(return_value); - return; + RETURN_EMPTY_ARRAY(); } array_init(return_value); diff --git a/ext/standard/exec.c b/ext/standard/exec.c index ce3e8565ad200..762d8bee13c22 100644 --- a/ext/standard/exec.c +++ b/ext/standard/exec.c @@ -199,13 +199,12 @@ PHPAPI int php_exec(int type, const char *cmd, zval *array, zval *return_value) static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ { - char *cmd; - size_t cmd_len; + zend_string *cmd; zval *ret_code=NULL, *ret_array=NULL; int ret; ZEND_PARSE_PARAMETERS_START(1, (mode ? 2 : 3)) - Z_PARAM_STRING(cmd, cmd_len) + Z_PARAM_PATH_STR(cmd) Z_PARAM_OPTIONAL if (!mode) { Z_PARAM_ZVAL(ret_array) @@ -213,17 +212,13 @@ static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ Z_PARAM_ZVAL(ret_code) ZEND_PARSE_PARAMETERS_END(); - if (!cmd_len) { + if (UNEXPECTED(!ZSTR_LEN(cmd))) { zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } - if (strlen(cmd) != cmd_len) { - zend_argument_value_error(1, "must not contain any null bytes"); - RETURN_THROWS(); - } if (!ret_array) { - ret = php_exec(mode, cmd, NULL, return_value); + ret = php_exec(mode, ZSTR_VAL(cmd), NULL, return_value); } else { if (Z_TYPE_P(Z_REFVAL_P(ret_array)) == IS_ARRAY) { ZVAL_DEREF(ret_array); @@ -235,7 +230,7 @@ static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ } } - ret = php_exec(2, cmd, ret_array, return_value); + ret = php_exec(2, ZSTR_VAL(cmd), ret_array, return_value); } if (ret_code) { ZEND_TRY_ASSIGN_REF_LONG(ret_code, ret); @@ -280,7 +275,7 @@ PHPAPI zend_string *php_escape_shell_cmd(const zend_string *unescaped_cmd) char *p = NULL; #endif - ZEND_ASSERT(ZSTR_LEN(unescaped_cmd) == strlen(ZSTR_VAL(unescaped_cmd)) && "Must be a binary safe string"); + ZEND_ASSERT(!zend_str_has_nul_byte(unescaped_cmd) && "Must be a binary safe string"); size_t l = ZSTR_LEN(unescaped_cmd); const char *str = ZSTR_VAL(unescaped_cmd); @@ -387,7 +382,7 @@ PHPAPI zend_string *php_escape_shell_arg(const zend_string *unescaped_arg) size_t x, y = 0; zend_string *cmd; - ZEND_ASSERT(ZSTR_LEN(unescaped_arg) == strlen(ZSTR_VAL(unescaped_arg)) && "Must be a binary safe string"); + ZEND_ASSERT(!zend_str_has_nul_byte(unescaped_arg) && "Must be a binary safe string"); size_t l = ZSTR_LEN(unescaped_arg); const char *str = ZSTR_VAL(unescaped_arg); diff --git a/ext/standard/file.c b/ext/standard/file.c index 4e136bedf5fab..ab6ed4fbadd2d 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -98,6 +98,7 @@ php_file_globals file_globals; # include #endif +#include "zend_attributes.h" #include "file_arginfo.h" /* }}} */ diff --git a/ext/standard/file.stub.php b/ext/standard/file.stub.php index 591169a37e001..5e12c43f397c7 100644 --- a/ext/standard/file.stub.php +++ b/ext/standard/file.stub.php @@ -444,15 +444,10 @@ */ const FILE_NO_DEFAULT_CONTEXT = UNKNOWN; -/** - * @var int - * @deprecated - */ +#[\Deprecated(since: '8.1', message: 'as the constant has no effect')] const FILE_TEXT = 0; -/** - * @var int - * @deprecated - */ + +#[\Deprecated(since: '8.1', message: 'as the constant has no effect')] const FILE_BINARY = 0; #ifdef HAVE_FNMATCH diff --git a/ext/standard/file_arginfo.h b/ext/standard/file_arginfo.h index 7dc8fcf80aabe..073e7951ad8c3 100644 --- a/ext/standard/file_arginfo.h +++ b/ext/standard/file_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e9a566d5ef96f781074027b1b3ff1824d0208b47 */ + * Stub hash: c394e14cd32587ce9ad0503e21c6c4cf5b301697 */ static void register_file_symbols(int module_number) { @@ -108,8 +108,8 @@ static void register_file_symbols(int module_number) REGISTER_LONG_CONSTANT("FILE_SKIP_EMPTY_LINES", PHP_FILE_SKIP_EMPTY_LINES, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILE_APPEND", PHP_FILE_APPEND, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILE_NO_DEFAULT_CONTEXT", PHP_FILE_NO_DEFAULT_CONTEXT, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FILE_TEXT", 0, CONST_PERSISTENT | CONST_DEPRECATED); - REGISTER_LONG_CONSTANT("FILE_BINARY", 0, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_FILE_TEXT = REGISTER_LONG_CONSTANT("FILE_TEXT", 0, CONST_PERSISTENT | CONST_DEPRECATED); + zend_constant *const_FILE_BINARY = REGISTER_LONG_CONSTANT("FILE_BINARY", 0, CONST_PERSISTENT | CONST_DEPRECATED); #if defined(HAVE_FNMATCH) REGISTER_LONG_CONSTANT("FNM_NOESCAPE", FNM_NOESCAPE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FNM_PATHNAME", FNM_PATHNAME, CONST_PERSISTENT); @@ -118,4 +118,18 @@ static void register_file_symbols(int module_number) #if defined(HAVE_FNMATCH) && defined(FNM_CASEFOLD) REGISTER_LONG_CONSTANT("FNM_CASEFOLD", FNM_CASEFOLD, CONST_PERSISTENT); #endif + + + zend_attribute *attribute_Deprecated_const_FILE_TEXT_0 = zend_add_global_constant_attribute(const_FILE_TEXT, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_FILE_TEXT_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_FILE_TEXT_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_FILE_TEXT_0_arg1_str = zend_string_init("as the constant has no effect", strlen("as the constant has no effect"), 1); + ZVAL_STR(&attribute_Deprecated_const_FILE_TEXT_0->args[1].value, attribute_Deprecated_const_FILE_TEXT_0_arg1_str); + attribute_Deprecated_const_FILE_TEXT_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_const_FILE_BINARY_0 = zend_add_global_constant_attribute(const_FILE_BINARY, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_const_FILE_BINARY_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_1)); + attribute_Deprecated_const_FILE_BINARY_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + ZVAL_STR_COPY(&attribute_Deprecated_const_FILE_BINARY_0->args[1].value, attribute_Deprecated_const_FILE_TEXT_0_arg1_str); + attribute_Deprecated_const_FILE_BINARY_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index 7cb54aa0aca49..85c2517ed91a0 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -749,7 +749,7 @@ PHPAPI void php_stat(zend_string *filename, int type, zval *return_value) php_stream_wrapper *wrapper = NULL; if (IS_ACCESS_CHECK(type)) { - if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) { + if (!ZSTR_LEN(filename) || zend_str_has_nul_byte(filename)) { if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) { php_error_docref(NULL, E_WARNING, "Filename contains null byte"); } @@ -821,7 +821,7 @@ PHPAPI void php_stat(zend_string *filename, int type, zval *return_value) } if (!wrapper) { - if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) { + if (!ZSTR_LEN(filename) || zend_str_has_nul_byte(filename)) { if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) { php_error_docref(NULL, E_WARNING, "Filename contains null byte"); } diff --git a/ext/standard/filters.c b/ext/standard/filters.c index 3dcbc4bc320ab..34393be54d8b4 100644 --- a/ext/standard/filters.c +++ b/ext/standard/filters.c @@ -1557,7 +1557,6 @@ static const php_stream_filter_ops strfilter_convert_ops = { static php_stream_filter *strfilter_convert_create(const char *filtername, zval *filterparams, uint8_t persistent) { php_convert_filter *inst; - php_stream_filter *retval = NULL; char *dot; int conv_mode = 0; @@ -1587,16 +1586,11 @@ static php_stream_filter *strfilter_convert_create(const char *filtername, zval if (php_convert_filter_ctor(inst, conv_mode, (filterparams != NULL ? Z_ARRVAL_P(filterparams) : NULL), filtername, persistent) != SUCCESS) { - goto out; - } - - retval = php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); -out: - if (retval == NULL) { pefree(inst, persistent); + return NULL; } - return retval; + return php_stream_filter_alloc(&strfilter_convert_ops, inst, persistent); } static const php_stream_filter_factory strfilter_convert_factory = { diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index cb7a471e935a6..2b9e00a57554c 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -23,6 +23,28 @@ #include "php_network.h" #include "file.h" +static size_t php_fsockopen_format_host_port(char **message, const char *prefix, size_t prefix_len, + const char *host, size_t host_len, zend_long port) +{ + char portbuf[32]; + int portlen = snprintf(portbuf, sizeof(portbuf), ":" ZEND_LONG_FMT, port); + size_t total_len = prefix_len + host_len + portlen; + + char *result = emalloc(total_len + 1); + + if (prefix_len > 0) { + memcpy(result, prefix, prefix_len); + } + memcpy(result + prefix_len, host, host_len); + memcpy(result + prefix_len + host_len, portbuf, portlen); + + result[total_len] = '\0'; + + *message = result; + + return total_len; +} + /* {{{ php_fsockopen() */ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) @@ -62,11 +84,12 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) } if (persistent) { - spprintf(&hashkey, 0, "pfsockopen__%s:" ZEND_LONG_FMT, host, port); + php_fsockopen_format_host_port(&hashkey, "pfsockopen__", strlen("pfsockopen__"), host, + host_len, port); } if (port > 0) { - hostname_len = spprintf(&hostname, 0, "%s:" ZEND_LONG_FMT, host, port); + hostname_len = php_fsockopen_format_host_port(&hostname, "", 0, host, host_len, port); } else { hostname_len = host_len; hostname = host; diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 51b7b311a9540..c747020ad6290 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -21,6 +21,7 @@ #include "php_globals.h" #include "php_network.h" #include "php_ini.h" +#include "zend_exceptions.h" #include #include @@ -38,6 +39,7 @@ #endif #include "php_standard.h" +#include "ext/uri/php_uri.h" #include #ifdef HAVE_SYS_SOCKET_H @@ -124,16 +126,22 @@ static int php_stream_ftp_stream_close(php_stream_wrapper *wrapper, php_stream * /* {{{ php_ftp_fopen_connect */ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context, php_stream **preuseid, - php_url **presource, int *puse_ssl, int *puse_ssl_on_data) + php_uri **presource, int *puse_ssl, int *puse_ssl_on_data) { php_stream *stream = NULL, *reuseid = NULL; - php_url *resource = NULL; + php_uri *resource = NULL; int result, use_ssl, use_ssl_on_data = 0; char tmp_line[512]; char *transport; int transport_len; - resource = php_url_parse(path); + const php_uri_parser *uri_parser = php_stream_context_get_uri_parser("ftp", context); + if (uri_parser == NULL) { + zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name()); + return NULL; + } + + resource = php_uri_parse_to_struct(uri_parser, path, strlen(path), PHP_URI_COMPONENT_READ_MODE_RAW, true); if (resource == NULL || resource->path == NULL) { if (resource && presource) { *presource = resource; @@ -254,12 +262,12 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char if (result >= 300 && result <= 399) { php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, tmp_line, 0); - if (resource->pass != NULL) { - ZSTR_LEN(resource->pass) = php_raw_url_decode(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass)); + if (resource->password != NULL) { + ZSTR_LEN(resource->password) = php_raw_url_decode(ZSTR_VAL(resource->password), ZSTR_LEN(resource->password)); - PHP_FTP_CNTRL_CHK(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass), "Invalid password %s") + PHP_FTP_CNTRL_CHK(ZSTR_VAL(resource->password), ZSTR_LEN(resource->password), "Invalid password %s") - php_stream_printf(stream, "PASS %s\r\n", ZSTR_VAL(resource->pass)); + php_stream_printf(stream, "PASS %s\r\n", ZSTR_VAL(resource->password)); } else { /* if the user has configured who they are, send that as the password */ @@ -299,7 +307,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char return stream; connect_errexit: - php_url_free(resource); + php_uri_struct_free(resource); if (stream) { php_stream_close(stream); @@ -404,7 +412,7 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa int options, zend_string **opened_path, php_stream_context *context STREAMS_DC) { php_stream *stream = NULL, *datastream = NULL; - php_url *resource = NULL; + php_uri *resource = NULL; char tmp_line[512]; char ip[sizeof("123.123.123.123")]; unsigned short portno; @@ -579,12 +587,12 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, const char *pa /* remember control stream */ datastream->wrapperthis = stream; - php_url_free(resource); + php_uri_struct_free(resource); return datastream; errexit: if (resource) { - php_url_free(resource); + php_uri_struct_free(resource); } if (stream) { php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result); @@ -683,7 +691,7 @@ static php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const ch { php_stream *stream, *reuseid, *datastream = NULL; php_ftp_dirstream_data *dirsdata; - php_url *resource = NULL; + php_uri *resource = NULL; int result = 0, use_ssl, use_ssl_on_data = 0; char *hoststart = NULL, tmp_line[512]; char ip[sizeof("123.123.123.123")]; @@ -745,7 +753,7 @@ static php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const ch goto opendir_errexit; } - php_url_free(resource); + php_uri_struct_free(resource); dirsdata = emalloc(sizeof *dirsdata); dirsdata->datastream = datastream; @@ -756,7 +764,7 @@ static php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const ch opendir_errexit: if (resource) { - php_url_free(resource); + php_uri_struct_free(resource); } if (stream) { php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result); @@ -773,7 +781,7 @@ static php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const ch static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context) { php_stream *stream = NULL; - php_url *resource = NULL; + php_uri *resource = NULL; int result; char tmp_line[512]; @@ -877,12 +885,12 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, #endif #endif php_stream_close(stream); - php_url_free(resource); + php_uri_struct_free(resource); return 0; stat_errexit: if (resource) { - php_url_free(resource); + php_uri_struct_free(resource); } if (stream) { php_stream_close(stream); @@ -895,7 +903,7 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) { php_stream *stream = NULL; - php_url *resource = NULL; + php_uri *resource = NULL; int result; char tmp_line[512]; @@ -925,13 +933,13 @@ static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, i goto unlink_errexit; } - php_url_free(resource); + php_uri_struct_free(resource); php_stream_close(stream); return 1; unlink_errexit: if (resource) { - php_url_free(resource); + php_uri_struct_free(resource); } if (stream) { php_stream_close(stream); @@ -944,18 +952,30 @@ static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, i static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context) { php_stream *stream = NULL; - php_url *resource_from = NULL, *resource_to = NULL; + php_uri *resource_from = NULL, *resource_to = NULL; int result; char tmp_line[512]; - resource_from = php_url_parse(url_from); - resource_to = php_url_parse(url_to); + const php_uri_parser *uri_parser = php_stream_context_get_uri_parser("ftp", context); + if (uri_parser == NULL) { + zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name()); + return 0; + } + + resource_from = php_uri_parse_to_struct(uri_parser, url_from, strlen(url_from), PHP_URI_COMPONENT_READ_MODE_RAW, true); + if (!resource_from) { + return 0; + } + + resource_to = php_uri_parse_to_struct(uri_parser, url_to, strlen(url_to), PHP_URI_COMPONENT_READ_MODE_RAW, true); + if (!resource_to) { + goto rename_errexit; + } + /* Must be same scheme (ftp/ftp or ftps/ftps), same host, and same port (or a 21/0 0/21 combination which is also "same") Also require paths to/from */ - if (!resource_from || - !resource_to || - !resource_from->scheme || + if (!resource_from->scheme || !resource_to->scheme || !zend_string_equals(resource_from->scheme, resource_to->scheme) || !resource_from->host || @@ -999,17 +1019,15 @@ static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_fr goto rename_errexit; } - php_url_free(resource_from); - php_url_free(resource_to); + php_uri_struct_free(resource_from); + php_uri_struct_free(resource_to); php_stream_close(stream); return 1; rename_errexit: - if (resource_from) { - php_url_free(resource_from); - } + php_uri_struct_free(resource_from); if (resource_to) { - php_url_free(resource_to); + php_uri_struct_free(resource_to); } if (stream) { php_stream_close(stream); @@ -1022,7 +1040,7 @@ static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_fr static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context) { php_stream *stream = NULL; - php_url *resource = NULL; + php_uri *resource = NULL; int result, recursive = options & PHP_STREAM_MKDIR_RECURSIVE; char tmp_line[512]; @@ -1089,7 +1107,7 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in efree(buf); } - php_url_free(resource); + php_uri_struct_free(resource); php_stream_close(stream); if (result < 200 || result > 299) { @@ -1101,7 +1119,7 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in mkdir_errexit: if (resource) { - php_url_free(resource); + php_uri_struct_free(resource); } if (stream) { php_stream_close(stream); @@ -1114,7 +1132,7 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) { php_stream *stream = NULL; - php_url *resource = NULL; + php_uri *resource = NULL; int result; char tmp_line[512]; @@ -1143,14 +1161,14 @@ static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const char *url, in goto rmdir_errexit; } - php_url_free(resource); + php_uri_struct_free(resource); php_stream_close(stream); return 1; rmdir_errexit: if (resource) { - php_url_free(resource); + php_uri_struct_free(resource); } if (stream) { php_stream_close(stream); diff --git a/ext/standard/head.c b/ext/standard/head.c index ccef4be16bdfd..0b497fdc42aab 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -79,7 +79,7 @@ PHPAPI bool php_header(void) #define ILLEGAL_COOKIE_CHARACTER "\",\", \";\", \" \", \"\\t\", \"\\r\", \"\\n\", \"\\013\", or \"\\014\"" PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, bool secure, bool httponly, - zend_string *samesite, bool url_encode) + zend_string *samesite, bool partitioned, bool url_encode) { zend_string *dt; sapi_header_line ctr = {0}; @@ -117,6 +117,11 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e return FAILURE; } #endif + if (partitioned && !secure) { + zend_value_error("%s(): \"partitioned\" option cannot be used without \"secure\" option", + get_active_function_name()); + return FAILURE; + } /* Should check value of SameSite? */ @@ -182,6 +187,9 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e smart_str_appends(&buf, COOKIE_SAMESITE); smart_str_append(&buf, samesite); } + if (partitioned) { + smart_str_appends(&buf, COOKIE_PARTITIONED); + } ctr.line = ZSTR_VAL(buf.s); ctr.line_len = (uint32_t) ZSTR_LEN(buf.s); @@ -192,7 +200,7 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e } static zend_result php_head_parse_cookie_options_array(HashTable *options, zend_long *expires, zend_string **path, - zend_string **domain, bool *secure, bool *httponly, zend_string **samesite) + zend_string **domain, bool *secure, bool *httponly, zend_string **samesite, bool *partitioned) { zend_string *key; zval *value; @@ -214,6 +222,8 @@ static zend_result php_head_parse_cookie_options_array(HashTable *options, zend_ *httponly = zval_is_true(value); } else if (zend_string_equals_literal_ci(key, "samesite")) { *samesite = zval_get_string(value); + } else if (zend_string_equals_literal_ci(key, "partitioned")) { + *partitioned = zval_is_true(value); } else { zend_value_error("%s(): option \"%s\" is invalid", get_active_function_name(), ZSTR_VAL(key)); return FAILURE; @@ -227,7 +237,7 @@ static void php_setcookie_common(INTERNAL_FUNCTION_PARAMETERS, bool is_raw) HashTable *options = NULL; zend_long expires = 0; zend_string *name, *value = NULL, *path = NULL, *domain = NULL, *samesite = NULL; - bool secure = 0, httponly = 0; + bool secure = 0, httponly = 0, partitioned = false; ZEND_PARSE_PARAMETERS_START(1, 7) Z_PARAM_STR(name) @@ -248,13 +258,13 @@ static void php_setcookie_common(INTERNAL_FUNCTION_PARAMETERS, bool is_raw) } if (FAILURE == php_head_parse_cookie_options_array(options, &expires, &path, - &domain, &secure, &httponly, &samesite) + &domain, &secure, &httponly, &samesite, &partitioned) ) { goto cleanup; } } - if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, !is_raw) == SUCCESS) { + if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, partitioned, !is_raw) == SUCCESS) { RETVAL_TRUE; } else { RETVAL_FALSE; diff --git a/ext/standard/head.h b/ext/standard/head.h index 32c2570a53255..0272fec2dc215 100644 --- a/ext/standard/head.h +++ b/ext/standard/head.h @@ -17,19 +17,20 @@ #ifndef HEAD_H #define HEAD_H -#define COOKIE_EXPIRES "; expires=" -#define COOKIE_MAX_AGE "; Max-Age=" -#define COOKIE_DOMAIN "; domain=" -#define COOKIE_PATH "; path=" -#define COOKIE_SECURE "; secure" -#define COOKIE_HTTPONLY "; HttpOnly" -#define COOKIE_SAMESITE "; SameSite=" +#define COOKIE_EXPIRES "; expires=" +#define COOKIE_MAX_AGE "; Max-Age=" +#define COOKIE_DOMAIN "; domain=" +#define COOKIE_PATH "; path=" +#define COOKIE_SECURE "; secure" +#define COOKIE_HTTPONLY "; HttpOnly" +#define COOKIE_SAMESITE "; SameSite=" +#define COOKIE_PARTITIONED "; Partitioned" extern PHP_RINIT_FUNCTION(head); PHPAPI bool php_header(void); PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, bool secure, bool httponly, - zend_string *samesite, bool url_encode); + zend_string *samesite, bool partitioned, bool url_encode); #endif diff --git a/ext/standard/hrtime.c b/ext/standard/hrtime.c index f8d5e3179136b..10853493b6390 100644 --- a/ext/standard/hrtime.c +++ b/ext/standard/hrtime.c @@ -46,7 +46,6 @@ delivered timestamp is monotonic and cannot be adjusted. */ PHP_FUNCTION(hrtime) { -#if ZEND_HRTIME_AVAILABLE bool get_as_num = 0; zend_hrtime_t t = zend_hrtime(); @@ -55,6 +54,7 @@ PHP_FUNCTION(hrtime) Z_PARAM_BOOL(get_as_num) ZEND_PARSE_PARAMETERS_END(); +#if ZEND_HRTIME_AVAILABLE if (UNEXPECTED(get_as_num)) { PHP_RETURN_HRTIME(t); } else { diff --git a/ext/standard/html.c b/ext/standard/html.c index 0c6231d590d88..af6e6ec94443b 100644 --- a/ext/standard/html.c +++ b/ext/standard/html.c @@ -809,112 +809,148 @@ static inline size_t write_octet_sequence(unsigned char *buf, enum entity_charse /* +2 is 1 because of rest (probably unnecessary), 1 because of terminating 0 */ #define TRAVERSE_FOR_ENTITIES_EXPAND_SIZE(oldlen) ((oldlen) + (oldlen) / 5 + 2) static void traverse_for_entities( - const char *old, - size_t oldlen, - zend_string *ret, /* should have allocated TRAVERSE_FOR_ENTITIES_EXPAND_SIZE(olden) */ - int all, - int flags, + const zend_string *input, + zend_string *output, /* should have allocated TRAVERSE_FOR_ENTITIES_EXPAND_SIZE(olden) */ + const int all, + const int flags, const entity_ht *inv_map, - enum entity_charset charset) + const enum entity_charset charset) { - const char *p, - *lim; - char *q; - int doctype = flags & ENT_HTML_DOC_TYPE_MASK; - - lim = old + oldlen; /* terminator address */ - assert(*lim == '\0'); - - for (p = old, q = ZSTR_VAL(ret); p < lim;) { - unsigned code, code2 = 0; - const char *next = NULL; /* when set, next > p, otherwise possible inf loop */ - - /* Shift JIS, Big5 and HKSCS use multi-byte encodings where an - * ASCII range byte can be part of a multi-byte sequence. - * However, they start at 0x40, therefore if we find a 0x26 byte, - * we're sure it represents the '&' character. */ + const char *current_ptr = ZSTR_VAL(input); + const char *input_end = current_ptr + ZSTR_LEN(input); /* terminator address */ + char *output_ptr = ZSTR_VAL(output); + const int doctype = flags & ENT_HTML_DOC_TYPE_MASK; + + while (current_ptr < input_end) { + const char *ampersand_ptr = memchr(current_ptr, '&', input_end - current_ptr); + if (!ampersand_ptr) { + const size_t tail_len = input_end - current_ptr; + if (tail_len > 0) { + memcpy(output_ptr, current_ptr, tail_len); + output_ptr += tail_len; + } + break; + } - /* assumes there are no single-char entities */ - if (p[0] != '&' || (p + 3 >= lim)) { - *(q++) = *(p++); - continue; + /* Copy everything up to the found '&' */ + const size_t chunk_len = ampersand_ptr - current_ptr; + if (chunk_len > 0) { + memcpy(output_ptr, current_ptr, chunk_len); + output_ptr += chunk_len; } - /* now p[3] is surely valid and is no terminator */ - - /* numerical entity */ - if (p[1] == '#') { - next = &p[2]; - if (process_numeric_entity(&next, &code) == FAILURE) - goto invalid_code; - - /* If we're in htmlspecialchars_decode, we're only decoding entities - * that represent &, <, >, " and '. Is this one of them? */ - if (!all && (code > 63U || - stage3_table_be_apos_00000[code].data.ent.entity == NULL)) - goto invalid_code; - - /* are we allowed to decode this entity in this document type? - * HTML 5 is the only that has a character that cannot be used in - * a numeric entity but is allowed literally (U+000D). The - * unoptimized version would be ... || !numeric_entity_is_allowed(code) */ - if (!unicode_cp_is_allowed(code, doctype) || - (doctype == ENT_HTML_DOC_HTML5 && code == 0x0D)) - goto invalid_code; - } else { - const char *start; - size_t ent_len; + /* Now current_ptr points to the '&' character. */ + current_ptr = ampersand_ptr; - next = &p[1]; - start = next; + /* If there are less than 4 bytes remaining, there isn't enough for an entity - + * copy '&' as a normal character. */ + if (input_end - current_ptr < 4) { + const size_t remaining = input_end - current_ptr; + memcpy(output_ptr, current_ptr, remaining); + output_ptr += remaining; + break; + } - if (process_named_entity_html(&next, &start, &ent_len) == FAILURE) - goto invalid_code; + unsigned code = 0, code2 = 0; + const char *entity_end_ptr = NULL; - if (resolve_named_entity_html(start, ent_len, inv_map, &code, &code2) == FAILURE) { - if (doctype == ENT_HTML_DOC_XHTML && ent_len == 4 && start[0] == 'a' - && start[1] == 'p' && start[2] == 'o' && start[3] == 's') { - /* uses html4 inv_map, which doesn't include apos;. This is a - * hack to support it */ - code = (unsigned) '\''; + if (current_ptr[1] == '#') { + /* Processing numeric entity */ + const char *num_start = current_ptr + 2; + entity_end_ptr = num_start; + if (process_numeric_entity(&entity_end_ptr, &code) == FAILURE) { + goto invalid_incomplete_entity; + } + if (!all && (code > 63U || stage3_table_be_apos_00000[code].data.ent.entity == NULL)) { + /* If we're in htmlspecialchars_decode, we're only decoding entities + * that represent &, <, >, " and '. Is this one of them? */ + goto invalid_incomplete_entity; + } else if (!unicode_cp_is_allowed(code, doctype) || + (doctype == ENT_HTML_DOC_HTML5 && code == 0x0D)) { + /* are we allowed to decode this entity in this document type? + * HTML 5 is the only that has a character that cannot be used in + * a numeric entity but is allowed literally (U+000D). The + * unoptimized version would be ... || !numeric_entity_is_allowed(code) */ + goto invalid_incomplete_entity; + } + } else { + /* Processing named entity */ + const char *name_start = current_ptr + 1; + /* Search for ';' */ + const size_t max_search_len = MIN(LONGEST_ENTITY_LENGTH + 1, input_end - name_start); + const char *semi_colon_ptr = memchr(name_start, ';', max_search_len); + if (!semi_colon_ptr) { + goto invalid_incomplete_entity; + } else { + const size_t name_len = semi_colon_ptr - name_start; + if (name_len == 0) { + goto invalid_incomplete_entity; } else { - goto invalid_code; + if (resolve_named_entity_html(name_start, name_len, inv_map, &code, &code2) == FAILURE) { + if (doctype == ENT_HTML_DOC_XHTML && name_len == 4 && + name_start[0] == 'a' && name_start[1] == 'p' && + name_start[2] == 'o' && name_start[3] == 's') + { + /* uses html4 inv_map, which doesn't include apos;. This is a + * hack to support it */ + code = (unsigned)'\''; + } else { + goto invalid_incomplete_entity; + } + } + entity_end_ptr = semi_colon_ptr; } } } - assert(*next == ';'); + /* At this stage the entity_end_ptr should be always set. */ + ZEND_ASSERT(entity_end_ptr != NULL); - if (((code == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) || - (code == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE))) - /* && code2 == '\0' always true for current maps */) - goto invalid_code; + /* Check if quotes are allowed for entities representing ' or " */ + if ((code == '\'' && !(flags & ENT_HTML_QUOTE_SINGLE)) || + (code == '"' && !(flags & ENT_HTML_QUOTE_DOUBLE))) + { + goto invalid_complete_entity; + } /* UTF-8 doesn't need mapping (ISO-8859-1 doesn't either, but * the call is needed to ensure the codepoint <= U+00FF) */ if (charset != cs_utf_8) { /* replace unicode code point */ - if (map_from_unicode(code, charset, &code) == FAILURE || code2 != 0) - goto invalid_code; /* not representable in target charset */ + if (map_from_unicode(code, charset, &code) == FAILURE || code2 != 0) { + goto invalid_complete_entity; + } } - q += write_octet_sequence((unsigned char*)q, charset, code); + /* Write the parsed entity into the output buffer */ + output_ptr += write_octet_sequence((unsigned char*)output_ptr, charset, code); if (code2) { - q += write_octet_sequence((unsigned char*)q, charset, code2); + output_ptr += write_octet_sequence((unsigned char*)output_ptr, charset, code2); } + /* Move current_ptr past the semicolon */ + current_ptr = entity_end_ptr + 1; + continue; - /* jump over the valid entity; may go beyond size of buffer; np */ - p = next + 1; +invalid_incomplete_entity: + /* If the entity is invalid at parse stage or entity_end_ptr was never found, copy '&' as normal */ + *output_ptr++ = *current_ptr++; continue; -invalid_code: - for (; p < next; p++) { - *(q++) = *p; +invalid_complete_entity: + /* If the entity became invalid after we found entity_end_ptr */ + if (entity_end_ptr) { + const size_t len = entity_end_ptr - current_ptr; + memcpy(output_ptr, current_ptr, len); + output_ptr += len; + current_ptr = entity_end_ptr; + } else { + *output_ptr++ = *current_ptr++; } + continue; } - *q = '\0'; - ZSTR_LEN(ret) = (size_t)(q - ZSTR_VAL(ret)); + *output_ptr = '\0'; + ZSTR_LEN(output) = (size_t)(output_ptr - ZSTR_VAL(output)); } /* }}} */ @@ -999,7 +1035,7 @@ PHPAPI zend_string *php_unescape_html_entities(zend_string *str, int all, int fl inverse_map = unescape_inverse_map(all, flags); /* replace numeric entities */ - traverse_for_entities(ZSTR_VAL(str), ZSTR_LEN(str), ret, all, flags, inverse_map, charset); + traverse_for_entities(str, ret, all, flags, inverse_map, charset); return ret; } @@ -1320,6 +1356,9 @@ static void php_html_entities(INTERNAL_FUNCTION_PARAMETERS, int all) Z_PARAM_BOOL(double_encode); ZEND_PARSE_PARAMETERS_END(); + if (ZSTR_LEN(str) == 0) { + RETURN_EMPTY_STRING(); + } replaced = php_escape_html_entities_ex( (unsigned char*)ZSTR_VAL(str), ZSTR_LEN(str), all, (int) flags, hint_charset ? ZSTR_VAL(hint_charset) : NULL, double_encode, /* quiet */ 0); diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 9fefe153622fc..b8ede088517ca 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -20,11 +20,13 @@ #include "php.h" #include "php_globals.h" +#include "ext/uri/php_uri.h" #include "php_streams.h" #include "php_network.h" #include "php_ini.h" #include "ext/standard/basic_functions.h" #include "zend_smart_str.h" +#include "zend_exceptions.h" #include #include @@ -358,7 +360,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, zval *response_header STREAMS_DC) /* {{{ */ { php_stream *stream = NULL; - php_url *resource = NULL; + php_uri *resource = NULL; int use_ssl; int use_proxy = 0; zend_string *tmp = NULL; @@ -391,7 +393,12 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, return NULL; } - resource = php_url_parse(path); + const php_uri_parser *uri_parser = php_stream_context_get_uri_parser("http", context); + if (uri_parser == NULL) { + zend_value_error("%s(): Provided stream context has invalid value for the \"uri_parser_class\" option", get_active_function_name()); + return NULL; + } + resource = php_uri_parse_to_struct(uri_parser, path, strlen(path), PHP_URI_COMPONENT_READ_MODE_RAW, true); if (resource == NULL) { return NULL; } @@ -403,7 +410,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "proxy")) == NULL || Z_TYPE_P(tmpzval) != IS_STRING || Z_STRLEN_P(tmpzval) == 0) { - php_url_free(resource); + php_uri_struct_free(resource); return php_stream_open_wrapper_ex(path, mode, REPORT_ERRORS, NULL, context); } /* Called from a non-http wrapper with http proxying requested (i.e. ftp) */ @@ -416,7 +423,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (strpbrk(mode, "awx+")) { php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper does not support writeable connections"); - php_url_free(resource); + php_uri_struct_free(resource); return NULL; } @@ -445,7 +452,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (request_fulluri && (strchr(path, '\n') != NULL || strchr(path, '\r') != NULL)) { php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper full URI path does not allow CR or LF characters"); - php_url_free(resource); + php_uri_struct_free(resource); zend_string_release(transport_string); return NULL; } @@ -461,7 +468,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (d > timeoutmax) { php_stream_wrapper_log_error(wrapper, options, "timeout must be lower than " ZEND_ULONG_FMT, (zend_ulong)timeoutmax); zend_string_release(transport_string); - php_url_free(resource); + php_uri_struct_free(resource); return NULL; } #ifndef PHP_WIN32 @@ -638,13 +645,9 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* protocol version we are speaking */ if (context && (tmpzval = php_stream_context_get_option(context, "http", "protocol_version")) != NULL) { - char *protocol_version; - spprintf(&protocol_version, 0, "%.1F", zval_get_double(tmpzval)); - smart_str_appends(&req_buf, " HTTP/"); - smart_str_appends(&req_buf, protocol_version); + smart_str_append_printf(&req_buf, "%.1F", zval_get_double(tmpzval)); smart_str_appends(&req_buf, "\r\n"); - efree(protocol_version); } else { smart_str_appends(&req_buf, " HTTP/1.1\r\n"); } @@ -746,33 +749,31 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* auth header if it was specified */ if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user) { - /* make scratch large enough to hold the whole URL (over-estimate) */ - size_t scratch_len = strlen(path) + 1; - char *scratch = emalloc(scratch_len); - zend_string *stmp; + smart_str scratch = {0}; /* decode the strings first */ php_url_decode(ZSTR_VAL(resource->user), ZSTR_LEN(resource->user)); - strcpy(scratch, ZSTR_VAL(resource->user)); - strcat(scratch, ":"); + smart_str_append(&scratch, resource->user); + smart_str_appendc(&scratch, ':'); /* Note: password is optional! */ - if (resource->pass) { - php_url_decode(ZSTR_VAL(resource->pass), ZSTR_LEN(resource->pass)); - strcat(scratch, ZSTR_VAL(resource->pass)); + if (resource->password) { + php_url_decode(ZSTR_VAL(resource->password), ZSTR_LEN(resource->password)); + smart_str_append(&scratch, resource->password); } - stmp = php_base64_encode((unsigned char*)scratch, strlen(scratch)); + zend_string *scratch_str = smart_str_extract(&scratch); + zend_string *stmp = php_base64_encode((unsigned char*)ZSTR_VAL(scratch_str), ZSTR_LEN(scratch_str)); smart_str_appends(&req_buf, "Authorization: Basic "); - smart_str_appends(&req_buf, ZSTR_VAL(stmp)); + smart_str_append(&req_buf, stmp); smart_str_appends(&req_buf, "\r\n"); php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0); + zend_string_efree(scratch_str); zend_string_free(stmp); - efree(scratch); } /* if the user has configured who they are, send a From: line */ @@ -1094,9 +1095,9 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, header_info.location = NULL; } - php_url_free(resource); + php_uri_struct_free(resource); /* check for invalid redirection URLs */ - if ((resource = php_url_parse(new_path)) == NULL) { + if ((resource = php_uri_parse_to_struct(uri_parser, new_path, strlen(new_path), PHP_URI_COMPONENT_READ_MODE_RAW, true)) == NULL) { php_stream_wrapper_log_error(wrapper, options, "Invalid redirect URL! %s", new_path); efree(new_path); goto out; @@ -1120,7 +1121,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* check for control characters in login, password & path */ if (strncasecmp(new_path, "http://", sizeof("http://") - 1) || strncasecmp(new_path, "https://", sizeof("https://") - 1)) { CHECK_FOR_CNTRL_CHARS(resource->user); - CHECK_FOR_CNTRL_CHARS(resource->pass); + CHECK_FOR_CNTRL_CHARS(resource->password); CHECK_FOR_CNTRL_CHARS(resource->path); } int new_flags = HTTP_WRAPPER_REDIRECTED; @@ -1151,7 +1152,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, } if (resource) { - php_url_free(resource); + php_uri_struct_free(resource); } if (stream) { diff --git a/ext/standard/image.c b/ext/standard/image.c index eeb1f1fa2813a..97dcc437c833e 100644 --- a/ext/standard/image.c +++ b/ext/standard/image.c @@ -51,24 +51,22 @@ PHPAPI const char php_sig_iff[4] = {'F','O','R','M'}; PHPAPI const char php_sig_ico[4] = {(char)0x00, (char)0x00, (char)0x01, (char)0x00}; PHPAPI const char php_sig_riff[4] = {'R', 'I', 'F', 'F'}; PHPAPI const char php_sig_webp[4] = {'W', 'E', 'B', 'P'}; +PHPAPI const char php_sig_ftyp[4] = {'f', 't', 'y', 'p'}; +PHPAPI const char php_sig_mif1[4] = {'m', 'i', 'f', '1'}; +PHPAPI const char php_sig_heic[4] = {'h', 'e', 'i', 'c'}; +PHPAPI const char php_sig_heix[4] = {'h', 'e', 'i', 'x'}; + +static zend_array php_image_handlers; +static int php_image_handler_next_id = IMAGE_FILETYPE_FIXED_COUNT; /* REMEMBER TO ADD MIME-TYPE TO FUNCTION php_image_type_to_mime_type */ /* PCX must check first 64bytes and byte 0=0x0a and byte2 < 0x06 */ -/* return info as a struct, to make expansion easier */ - -struct gfxinfo { - unsigned int width; - unsigned int height; - unsigned int bits; - unsigned int channels; -}; - /* {{{ php_handle_gif * routine to handle GIF files. If only everything were that easy... ;} */ -static struct gfxinfo *php_handle_gif (php_stream * stream) +static struct php_gfxinfo *php_handle_gif (php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; unsigned char dim[5]; if (php_stream_seek(stream, 3, SEEK_CUR)) @@ -77,7 +75,7 @@ static struct gfxinfo *php_handle_gif (php_stream * stream) if (php_stream_read(stream, (char*)dim, sizeof(dim)) != sizeof(dim)) return NULL; - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); result->width = (unsigned int)dim[0] | (((unsigned int)dim[1])<<8); result->height = (unsigned int)dim[2] | (((unsigned int)dim[3])<<8); result->bits = dim[4]&0x80 ? ((((unsigned int)dim[4])&0x07) + 1) : 0; @@ -88,9 +86,9 @@ static struct gfxinfo *php_handle_gif (php_stream * stream) /* }}} */ /* {{{ php_handle_psd */ -static struct gfxinfo *php_handle_psd (php_stream * stream) +static struct php_gfxinfo *php_handle_psd (php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; unsigned char dim[8]; if (php_stream_seek(stream, 11, SEEK_CUR)) @@ -99,7 +97,7 @@ static struct gfxinfo *php_handle_psd (php_stream * stream) if (php_stream_read(stream, (char*)dim, sizeof(dim)) != sizeof(dim)) return NULL; - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); result->height = (((unsigned int)dim[0]) << 24) + (((unsigned int)dim[1]) << 16) + (((unsigned int)dim[2]) << 8) + ((unsigned int)dim[3]); result->width = (((unsigned int)dim[4]) << 24) + (((unsigned int)dim[5]) << 16) + (((unsigned int)dim[6]) << 8) + ((unsigned int)dim[7]); @@ -108,9 +106,9 @@ static struct gfxinfo *php_handle_psd (php_stream * stream) /* }}} */ /* {{{ php_handle_bmp */ -static struct gfxinfo *php_handle_bmp (php_stream * stream) +static struct php_gfxinfo *php_handle_bmp (php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; unsigned char dim[16]; int size; @@ -122,12 +120,12 @@ static struct gfxinfo *php_handle_bmp (php_stream * stream) size = (((unsigned int)dim[ 3]) << 24) + (((unsigned int)dim[ 2]) << 16) + (((unsigned int)dim[ 1]) << 8) + ((unsigned int) dim[ 0]); if (size == 12) { - result = (struct gfxinfo *) ecalloc (1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc (1, sizeof(struct php_gfxinfo)); result->width = (((unsigned int)dim[ 5]) << 8) + ((unsigned int) dim[ 4]); result->height = (((unsigned int)dim[ 7]) << 8) + ((unsigned int) dim[ 6]); result->bits = ((unsigned int)dim[11]); } else if (size > 12 && (size <= 64 || size == 108 || size == 124)) { - result = (struct gfxinfo *) ecalloc (1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc (1, sizeof(struct php_gfxinfo)); result->width = (((unsigned int)dim[ 7]) << 24) + (((unsigned int)dim[ 6]) << 16) + (((unsigned int)dim[ 5]) << 8) + ((unsigned int) dim[ 4]); result->height = (((unsigned int)dim[11]) << 24) + (((unsigned int)dim[10]) << 16) + (((unsigned int)dim[ 9]) << 8) + ((unsigned int) dim[ 8]); result->height = abs((int32_t)result->height); @@ -158,9 +156,9 @@ static unsigned long int php_swf_get_bits (unsigned char* buffer, unsigned int p #if defined(HAVE_ZLIB) && !defined(COMPILE_DL_ZLIB) /* {{{ php_handle_swc */ -static struct gfxinfo *php_handle_swc(php_stream * stream) +static struct php_gfxinfo *php_handle_swc(php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; long bits; unsigned char a[64]; @@ -227,7 +225,7 @@ static struct gfxinfo *php_handle_swc(php_stream * stream) } if (!status) { - result = (struct gfxinfo *) ecalloc (1, sizeof (struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc (1, sizeof (struct php_gfxinfo)); bits = php_swf_get_bits (b, 0, 5); result->width = (php_swf_get_bits (b, 5 + bits, bits) - php_swf_get_bits (b, 5, bits)) / 20; @@ -244,9 +242,9 @@ static struct gfxinfo *php_handle_swc(php_stream * stream) #endif /* {{{ php_handle_swf */ -static struct gfxinfo *php_handle_swf (php_stream * stream) +static struct php_gfxinfo *php_handle_swf (php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; long bits; unsigned char a[32]; @@ -256,7 +254,7 @@ static struct gfxinfo *php_handle_swf (php_stream * stream) if (php_stream_read(stream, (char*)a, sizeof(a)) != sizeof(a)) return NULL; - result = (struct gfxinfo *) ecalloc (1, sizeof (struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc (1, sizeof (struct php_gfxinfo)); bits = php_swf_get_bits (a, 0, 5); result->width = (php_swf_get_bits (a, 5 + bits, bits) - php_swf_get_bits (a, 5, bits)) / 20; @@ -270,9 +268,9 @@ static struct gfxinfo *php_handle_swf (php_stream * stream) /* {{{ php_handle_png * routine to handle PNG files */ -static struct gfxinfo *php_handle_png (php_stream * stream) +static struct php_gfxinfo *php_handle_png (php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; unsigned char dim[9]; /* Width: 4 bytes * Height: 4 bytes @@ -289,7 +287,7 @@ static struct gfxinfo *php_handle_png (php_stream * stream) if((php_stream_read(stream, (char*)dim, sizeof(dim))) < sizeof(dim)) return NULL; - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); result->width = (((unsigned int)dim[0]) << 24) + (((unsigned int)dim[1]) << 16) + (((unsigned int)dim[2]) << 8) + ((unsigned int)dim[3]); result->height = (((unsigned int)dim[4]) << 24) + (((unsigned int)dim[5]) << 16) + (((unsigned int)dim[6]) << 8) + ((unsigned int)dim[7]); result->bits = (unsigned int)dim[8]; @@ -448,9 +446,9 @@ static int php_read_APP(php_stream * stream, unsigned int marker, zval *info) /* {{{ php_handle_jpeg main loop to parse JPEG structure */ -static struct gfxinfo *php_handle_jpeg (php_stream * stream, zval *info) +static struct php_gfxinfo *php_handle_jpeg (php_stream * stream, zval *info) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; unsigned int marker = M_PSEUDO; unsigned short length, ff_read=1; @@ -473,7 +471,7 @@ static struct gfxinfo *php_handle_jpeg (php_stream * stream, zval *info) case M_SOF15: if (result == NULL) { /* handle SOFn block */ - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); length = php_read2(stream); result->bits = php_stream_getc(stream); result->height = php_read2(stream); @@ -576,9 +574,9 @@ static unsigned int php_read4(php_stream * stream) /* {{{ php_handle_jpc Main loop to parse JPEG2000 raw codestream structure */ -static struct gfxinfo *php_handle_jpc(php_stream * stream) +static struct php_gfxinfo *php_handle_jpc(php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; int highest_bit_depth, bit_depth; unsigned char first_marker_id; unsigned int i; @@ -599,7 +597,7 @@ static struct gfxinfo *php_handle_jpc(php_stream * stream) return NULL; } - result = (struct gfxinfo *)ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *)ecalloc(1, sizeof(struct php_gfxinfo)); php_read2(stream); /* Lsiz */ php_read2(stream); /* Rsiz */ @@ -647,9 +645,9 @@ static struct gfxinfo *php_handle_jpc(php_stream * stream) /* {{{ php_handle_jp2 main loop to parse JPEG 2000 JP2 wrapper format structure */ -static struct gfxinfo *php_handle_jp2(php_stream *stream) +static struct php_gfxinfo *php_handle_jp2(php_stream *stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; unsigned int box_length; unsigned int box_type; char jp2c_box_id[] = {(char)0x6a, (char)0x70, (char)0x32, (char)0x63}; @@ -773,9 +771,9 @@ static unsigned php_ifd_get32u(void *Long, int motorola_intel) /* {{{ php_handle_tiff main loop to parse TIFF structure */ -static struct gfxinfo *php_handle_tiff (php_stream * stream, zval *info, int motorola_intel) +static struct php_gfxinfo *php_handle_tiff (php_stream * stream, zval *info, int motorola_intel) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; int i, num_entries; unsigned char *dir_entry; size_t ifd_size, dir_size, entry_value, width=0, height=0, ifd_addr; @@ -841,7 +839,7 @@ static struct gfxinfo *php_handle_tiff (php_stream * stream, zval *info, int mot efree(ifd_data); if ( width && height) { /* not the same when in for-loop */ - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); result->height = height; result->width = width; result->bits = 0; @@ -853,9 +851,9 @@ static struct gfxinfo *php_handle_tiff (php_stream * stream, zval *info, int mot /* }}} */ /* {{{ php_handle_psd */ -static struct gfxinfo *php_handle_iff(php_stream * stream) +static struct php_gfxinfo *php_handle_iff(php_stream * stream) { - struct gfxinfo * result; + struct php_gfxinfo * result; unsigned char a[10]; int chunkId; int size; @@ -889,7 +887,7 @@ static struct gfxinfo *php_handle_iff(php_stream * stream) height = php_ifd_get16s(a+2, 1); bits = a[8] & 0xff; if (width > 0 && height > 0 && bits > 0 && bits < 33) { - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); result->width = width; result->height = height; result->bits = bits; @@ -914,7 +912,7 @@ static struct gfxinfo *php_handle_iff(php_stream * stream) * int Number of columns * int Number of rows */ -static int php_get_wbmp(php_stream *stream, struct gfxinfo **result, int check) +static int php_get_wbmp(php_stream *stream, struct php_gfxinfo **result, int check) { int i, width = 0, height = 0; @@ -975,9 +973,9 @@ static int php_get_wbmp(php_stream *stream, struct gfxinfo **result, int check) /* }}} */ /* {{{ php_handle_wbmp */ -static struct gfxinfo *php_handle_wbmp(php_stream * stream) +static struct php_gfxinfo *php_handle_wbmp(php_stream * stream) { - struct gfxinfo *result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + struct php_gfxinfo *result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); if (!php_get_wbmp(stream, &result, 0)) { efree(result); @@ -989,7 +987,7 @@ static struct gfxinfo *php_handle_wbmp(php_stream * stream) /* }}} */ /* {{{ php_get_xbm */ -static int php_get_xbm(php_stream *stream, struct gfxinfo **result) +static int php_get_xbm(php_stream *stream, struct php_gfxinfo **result) { char *fline; char *iname; @@ -1036,7 +1034,7 @@ static int php_get_xbm(php_stream *stream, struct gfxinfo **result) if (width && height) { if (result) { - *result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + *result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); (*result)->width = width; (*result)->height = height; } @@ -1048,18 +1046,18 @@ static int php_get_xbm(php_stream *stream, struct gfxinfo **result) /* }}} */ /* {{{ php_handle_xbm */ -static struct gfxinfo *php_handle_xbm(php_stream * stream) +static struct php_gfxinfo *php_handle_xbm(php_stream * stream) { - struct gfxinfo *result; + struct php_gfxinfo *result; php_get_xbm(stream, &result); return result; } /* }}} */ /* {{{ php_handle_ico */ -static struct gfxinfo *php_handle_ico(php_stream * stream) +static struct php_gfxinfo *php_handle_ico(php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; unsigned char dim[16]; int num_icons = 0; @@ -1071,7 +1069,7 @@ static struct gfxinfo *php_handle_ico(php_stream * stream) if (num_icons < 1 || num_icons > 255) return NULL; - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); while (num_icons > 0) { @@ -1098,9 +1096,9 @@ static struct gfxinfo *php_handle_ico(php_stream * stream) /* }}} */ /* {{{ php_handle_webp */ -static struct gfxinfo *php_handle_webp(php_stream * stream) +static struct php_gfxinfo *php_handle_webp(php_stream * stream) { - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; const char sig[3] = {'V', 'P', '8'}; unsigned char buf[18]; char format; @@ -1121,7 +1119,7 @@ static struct gfxinfo *php_handle_webp(php_stream * stream) return NULL; } - result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo *) ecalloc(1, sizeof(struct php_gfxinfo)); switch (format) { case ' ': @@ -1183,14 +1181,14 @@ static void php_avif_stream_skip(void* stream, size_t num_bytes) { * declared as invalid. Around 450 bytes are usually enough. * Transforms such as mirror and rotation are not applied on width and height. */ -static struct gfxinfo *php_handle_avif(php_stream * stream) { - struct gfxinfo* result = NULL; +static struct php_gfxinfo *php_handle_avif(php_stream * stream) { + struct php_gfxinfo* result = NULL; AvifInfoFeatures features; struct php_avif_stream avif_stream; avif_stream.stream = stream; if (AvifInfoGetFeaturesStream(&avif_stream, php_avif_stream_read, php_avif_stream_skip, &features) == kAvifInfoOk) { - result = (struct gfxinfo*)ecalloc(1, sizeof(struct gfxinfo)); + result = (struct php_gfxinfo*)ecalloc(1, sizeof(struct php_gfxinfo)); result->width = features.width; result->height = features.height; result->bits = features.bit_depth; @@ -1200,7 +1198,7 @@ static struct gfxinfo *php_handle_avif(php_stream * stream) { } /* }}} */ -/* {{{ php_is_image_avif +/* * Detect whether an image is of type AVIF * * Only the first "ftyp" box is read. @@ -1210,16 +1208,12 @@ bool php_is_image_avif(php_stream* stream) { struct php_avif_stream avif_stream; avif_stream.stream = stream; - if (AvifInfoIdentifyStream(&avif_stream, php_avif_stream_read, php_avif_stream_skip) == kAvifInfoOk) { - return 1; - } - return 0; + return AvifInfoIdentifyStream(&avif_stream, php_avif_stream_read, php_avif_stream_skip) == kAvifInfoOk; } -/* }}} */ /* {{{ php_image_type_to_mime_type * Convert internal image_type to mime type */ -PHPAPI char * php_image_type_to_mime_type(int image_type) +PHPAPI const char * php_image_type_to_mime_type(int image_type) { switch( image_type) { case IMAGE_FILETYPE_GIF: @@ -1254,7 +1248,15 @@ PHPAPI char * php_image_type_to_mime_type(int image_type) return "image/webp"; case IMAGE_FILETYPE_AVIF: return "image/avif"; - default: + case IMAGE_FILETYPE_HEIF: + return "image/heif"; + default: { + const struct php_image_handler *handler = zend_hash_index_find_ptr(&php_image_handlers, (zend_ulong) image_type); + if (handler) { + return handler->mime_type; + } + ZEND_FALLTHROUGH; + } case IMAGE_FILETYPE_UNKNOWN: return "application/octet-stream"; /* suppose binary format */ } @@ -1270,7 +1272,7 @@ PHP_FUNCTION(image_type_to_mime_type) Z_PARAM_LONG(p_image_type) ZEND_PARSE_PARAMETERS_END(); - ZVAL_STRING(return_value, (char*)php_image_type_to_mime_type(p_image_type)); + ZVAL_STRING(return_value, php_image_type_to_mime_type(p_image_type)); } /* }}} */ @@ -1339,6 +1341,16 @@ PHP_FUNCTION(image_type_to_extension) case IMAGE_FILETYPE_AVIF: imgext = ".avif"; break; + case IMAGE_FILETYPE_HEIF: + imgext = ".heif"; + break; + default: { + const struct php_image_handler *handler = zend_hash_index_find_ptr(&php_image_handlers, (zend_ulong) image_type); + if (handler) { + imgext = handler->extension; + } + break; + } } if (imgext) { @@ -1423,6 +1435,11 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp return IMAGE_FILETYPE_JP2; } + if (twelve_bytes_read && !memcmp(filetype + 4, php_sig_ftyp, 4) && + (!memcmp(filetype + 8, php_sig_mif1, 4) || !memcmp(filetype + 8, php_sig_heic, 4) || !memcmp(filetype + 8, php_sig_heix, 4))) { + return IMAGE_FILETYPE_HEIF; + } + if (!php_stream_rewind(stream) && php_is_image_avif(stream)) { return IMAGE_FILETYPE_AVIF; } @@ -1441,6 +1458,15 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp return IMAGE_FILETYPE_XBM; } + zend_ulong h; + zval *zv; + ZEND_HASH_FOREACH_NUM_KEY_VAL(&php_image_handlers, h, zv) { + const struct php_image_handler *handler = Z_PTR_P(zv); + if (handler->identify(stream) == SUCCESS) { + return (int) h; + } + } ZEND_HASH_FOREACH_END(); + return IMAGE_FILETYPE_UNKNOWN; } /* }}} */ @@ -1448,7 +1474,8 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp static void php_getimagesize_from_stream(php_stream *stream, char *input, zval *info, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { int itype = 0; - struct gfxinfo *result = NULL; + struct php_gfxinfo *result = NULL; + const char *mime_type = NULL; if (!stream) { RETURN_FALSE; @@ -1473,6 +1500,7 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval * result = php_handle_swf(stream); break; case IMAGE_FILETYPE_SWC: + /* TODO: with the new php_image_register_handler() APIs, this restriction could be solved */ #if defined(HAVE_ZLIB) && !defined(COMPILE_DL_ZLIB) result = php_handle_swc(stream); #else @@ -1515,19 +1543,35 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval * case IMAGE_FILETYPE_AVIF: result = php_handle_avif(stream); break; - default: + case IMAGE_FILETYPE_HEIF: + if (!php_stream_rewind(stream)) { + result = php_handle_avif(stream); + } + break; + default: { + struct php_image_handler* handler = zend_hash_index_find_ptr(&php_image_handlers, (zend_ulong) itype); + if (handler) { + result = handler->get_info(stream); + mime_type = handler->mime_type; + break; + } + ZEND_FALLTHROUGH; + } case IMAGE_FILETYPE_UNKNOWN: break; } if (result) { - char temp[MAX_LENGTH_OF_LONG * 2 + sizeof("width=\"\" height=\"\"")]; array_init(return_value); add_index_long(return_value, 0, result->width); add_index_long(return_value, 1, result->height); add_index_long(return_value, 2, itype); - snprintf(temp, sizeof(temp), "width=\"%d\" height=\"%d\"", result->width, result->height); - add_index_string(return_value, 3, temp); + if ((!result->width_unit || zend_string_equals_literal(result->width_unit, "px")) + && (!result->height_unit || zend_string_equals_literal(result->height_unit, "px"))) { + char temp[MAX_LENGTH_OF_LONG * 2 + sizeof("width=\"\" height=\"\"")]; + snprintf(temp, sizeof(temp), "width=\"%d\" height=\"%d\"", result->width, result->height); + add_index_string(return_value, 3, temp); + } if (result->bits != 0) { add_assoc_long(return_value, "bits", result->bits); @@ -1535,7 +1579,19 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval * if (result->channels != 0) { add_assoc_long(return_value, "channels", result->channels); } - add_assoc_string(return_value, "mime", (char*)php_image_type_to_mime_type(itype)); + add_assoc_string(return_value, "mime", mime_type ? mime_type : php_image_type_to_mime_type(itype)); + + if (result->width_unit) { + add_assoc_str(return_value, "width_unit", result->width_unit); + } else { + add_assoc_string(return_value, "width_unit", "px"); + } + if (result->height_unit) { + add_assoc_str(return_value, "height_unit", result->height_unit); + } else { + add_assoc_string(return_value, "height_unit", "px"); + } + efree(result); } else { RETURN_FALSE; @@ -1558,7 +1614,7 @@ static void php_getimagesize_from_any(INTERNAL_FUNCTION_PARAMETERS, int mode) { Z_PARAM_ZVAL(info) ZEND_PARSE_PARAMETERS_END(); - if (mode == FROM_PATH && CHECK_NULL_PATH(ZSTR_VAL(input), ZSTR_LEN(input))) { + if (mode == FROM_PATH && zend_str_has_nul_byte(input)) { zend_argument_value_error(1, "must not contain any null bytes"); RETURN_THROWS(); } @@ -1598,3 +1654,36 @@ PHP_FUNCTION(getimagesizefromstring) php_getimagesize_from_any(INTERNAL_FUNCTION_PARAM_PASSTHRU, FROM_DATA); } /* }}} */ + +PHP_MINIT_FUNCTION(image) +{ + zend_hash_init(&php_image_handlers, 4, NULL, NULL, true); + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(image) +{ +#ifdef ZTS + if (!tsrm_is_main_thread()) { + return SUCCESS; + } +#endif + zend_hash_destroy(&php_image_handlers); + return SUCCESS; +} + +extern zend_module_entry basic_functions_module; + +int php_image_register_handler(const struct php_image_handler *handler) +{ + zend_hash_index_add_ptr(&php_image_handlers, (zend_ulong) php_image_handler_next_id, (void *) handler); + zend_register_long_constant(handler->const_name, strlen(handler->const_name), php_image_handler_next_id, CONST_PERSISTENT, basic_functions_module.module_number); + Z_LVAL_P(zend_get_constant_str(ZEND_STRL("IMAGETYPE_COUNT")))++; + return php_image_handler_next_id++; +} + +zend_result php_image_unregister_handler(int image_type) +{ + ZEND_ASSERT(image_type >= IMAGE_FILETYPE_FIXED_COUNT); + return zend_hash_index_del(&php_image_handlers, (zend_ulong) image_type); +} diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 41e2a02078e78..f6161782bdd76 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -290,7 +290,7 @@ PHP_FUNCTION(mail) ZEND_PARSE_PARAMETERS_END(); if (headers_str) { - if (strlen(ZSTR_VAL(headers_str)) != ZSTR_LEN(headers_str)) { + if (UNEXPECTED(zend_str_has_nul_byte(headers_str))) { zend_argument_value_error(4, "must not contain any null bytes"); RETURN_THROWS(); } @@ -494,7 +494,27 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c MAIL_RET(false); } - char *line_sep = PG(mail_mixed_lf_and_crlf) ? "\n" : "\r\n"; + char *line_sep; + zend_string *cr_lf_mode = PG(mail_cr_lf_mode); + + if (cr_lf_mode && !zend_string_equals_literal(cr_lf_mode, "crlf")) { + if (zend_string_equals_literal(cr_lf_mode, "lf")) { + line_sep = "\n"; + } else if (zend_string_equals_literal(cr_lf_mode, "mixed")) { + line_sep = "\n"; + } else if (zend_string_equals_literal(cr_lf_mode, "os")) { +#ifdef PHP_WIN32 + line_sep = "\r\n"; +#else + line_sep = "\n"; +#endif + } else { + ZEND_ASSERT(0 && "Unexpected cr_lf_mode value"); + } + } else { + /* CRLF is default mode, but respect mail.mixed_lf_and_crlf for backward compatibility */ + line_sep = PG(mail_mixed_lf_and_crlf) ? "\n" : "\r\n"; + } if (PG(mail_x_header)) { const char *tmp = zend_get_executed_filename(); @@ -586,7 +606,43 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c if (hdr != NULL) { fprintf(sendmail, "%s%s", hdr, line_sep); } - fprintf(sendmail, "%s%s%s", line_sep, message, line_sep); + + fprintf(sendmail, "%s", line_sep); + + if (cr_lf_mode && zend_string_equals_literal(cr_lf_mode, "lf")) { + char *converted_message = NULL; + size_t msg_len = strlen(message); + size_t new_len = 0; + + for (size_t i = 0; i < msg_len - 1; ++i) { + if (message[i] == '\r' && message[i + 1] == '\n') { + ++new_len; + } + } + + if (new_len == 0) { + fprintf(sendmail, "%s", message); + } else { + converted_message = emalloc(msg_len - new_len + 1); + size_t j = 0; + for (size_t i = 0; i < msg_len; ++i) { + if (i < msg_len - 1 && message[i] == '\r' && message[i + 1] == '\n') { + converted_message[j++] = '\n'; + ++i; /* skip LF part */ + } else { + converted_message[j++] = message[i]; + } + } + + converted_message[j] = '\0'; + fprintf(sendmail, "%s", converted_message); + efree(converted_message); + } + } else { + fprintf(sendmail, "%s", message); + } + + fprintf(sendmail, "%s", line_sep); #ifdef PHP_WIN32 ret = pclose(sendmail); diff --git a/ext/standard/pack.c b/ext/standard/pack.c index d4c5cc1f04cfa..55da64897a2e7 100644 --- a/ext/standard/pack.c +++ b/ext/standard/pack.c @@ -19,7 +19,6 @@ #include #include #include -#include "pack.h" #define INC_OUTPUTPOS(a,b) \ if ((a) < 0 || ((INT_MAX - outputpos)/((int)b)) < (a)) { \ @@ -30,10 +29,23 @@ } \ outputpos += (a)*(b); +typedef enum { + PHP_LITTLE_ENDIAN, + PHP_BIG_ENDIAN, +} php_pack_endianness; + #ifdef WORDS_BIGENDIAN -#define MACHINE_LITTLE_ENDIAN 0 +# define MACHINE_LITTLE_ENDIAN 0 +# define PHP_MACHINE_ENDIAN PHP_BIG_ENDIAN #else -#define MACHINE_LITTLE_ENDIAN 1 +# define MACHINE_LITTLE_ENDIAN 1 +# define PHP_MACHINE_ENDIAN PHP_LITTLE_ENDIAN +#endif + +#ifdef ZEND_ENABLE_ZVAL_LONG64 +# define PHP_LONG_BSWAP(u) ZEND_BYTES_SWAP64(u) +#else +# define PHP_LONG_BSWAP(u) ZEND_BYTES_SWAP32(u) #endif typedef ZEND_SET_ALIGNED(1, uint16_t unaligned_uint16_t); @@ -42,41 +54,23 @@ typedef ZEND_SET_ALIGNED(1, uint64_t unaligned_uint64_t); typedef ZEND_SET_ALIGNED(1, unsigned int unaligned_uint); typedef ZEND_SET_ALIGNED(1, int unaligned_int); -/* Mapping of byte from char (8bit) to long for machine endian */ -static int byte_map[1]; - -/* Mappings of bytes from int (machine dependent) to int for machine endian */ -static int int_map[sizeof(int)]; - -/* Mappings of bytes from shorts (16bit) for all endian environments */ -static int machine_endian_short_map[2]; -static int big_endian_short_map[2]; -static int little_endian_short_map[2]; - -/* Mappings of bytes from longs (32bit) for all endian environments */ -static int machine_endian_long_map[4]; -static int big_endian_long_map[4]; -static int little_endian_long_map[4]; - -#if SIZEOF_ZEND_LONG > 4 -/* Mappings of bytes from quads (64bit) for all endian environments */ -static int machine_endian_longlong_map[8]; -static int big_endian_longlong_map[8]; -static int little_endian_longlong_map[8]; -#endif - /* {{{ php_pack */ -static void php_pack(zval *val, size_t size, int *map, char *output) +static void php_pack(const zval *val, size_t size, php_pack_endianness endianness, char *output) { - size_t i; - char *v; - - convert_to_long(val); - v = (char *) &Z_LVAL_P(val); + zend_ulong zl = zval_get_long(val); - for (i = 0; i < size; i++) { - *output++ = v[map[i]]; + if ((endianness == PHP_LITTLE_ENDIAN) != MACHINE_LITTLE_ENDIAN) { + zl = PHP_LONG_BSWAP(zl); +#if MACHINE_LITTLE_ENDIAN + zl >>= (sizeof(zl) - size) * 8; +#endif + } else { +#if !MACHINE_LITTLE_ENDIAN + zl <<= (sizeof(zl) - size) * 8; +#endif } + + memcpy(output, (const char *) &zl, size); } /* }}} */ @@ -88,10 +82,7 @@ ZEND_ATTRIBUTE_CONST static inline uint16_t php_pack_reverse_int16(uint16_t arg) /* {{{ php_pack_reverse_int32 */ ZEND_ATTRIBUTE_CONST static inline uint32_t php_pack_reverse_int32(uint32_t arg) { - uint32_t result; - result = ((arg & 0xFF) << 24) | ((arg & 0xFF00) << 8) | ((arg >> 8) & 0xFF00) | ((arg >> 24) & 0xFF); - - return result; + return ZEND_BYTES_SWAP32(arg); } /* }}} */ @@ -366,7 +357,7 @@ PHP_FUNCTION(pack) switch (code) { case 'h': case 'H': - INC_OUTPUTPOS((arg + (arg % 2)) / 2,1) /* 4 bit per arg */ + INC_OUTPUTPOS((arg / 2) + (arg % 2),1) /* 4 bit per arg */ break; case 'a': @@ -509,7 +500,7 @@ PHP_FUNCTION(pack) case 'c': case 'C': while (arg-- > 0) { - php_pack(&argv[currentarg++], 1, byte_map, &ZSTR_VAL(output)[outputpos]); + php_pack(&argv[currentarg++], 1, PHP_MACHINE_ENDIAN, &ZSTR_VAL(output)[outputpos]); outputpos++; } break; @@ -518,16 +509,16 @@ PHP_FUNCTION(pack) case 'S': case 'n': case 'v': { - int *map = machine_endian_short_map; + php_pack_endianness endianness = PHP_MACHINE_ENDIAN; if (code == 'n') { - map = big_endian_short_map; + endianness = PHP_BIG_ENDIAN; } else if (code == 'v') { - map = little_endian_short_map; + endianness = PHP_LITTLE_ENDIAN; } while (arg-- > 0) { - php_pack(&argv[currentarg++], 2, map, &ZSTR_VAL(output)[outputpos]); + php_pack(&argv[currentarg++], 2, endianness, &ZSTR_VAL(output)[outputpos]); outputpos += 2; } break; @@ -536,7 +527,7 @@ PHP_FUNCTION(pack) case 'i': case 'I': while (arg-- > 0) { - php_pack(&argv[currentarg++], sizeof(int), int_map, &ZSTR_VAL(output)[outputpos]); + php_pack(&argv[currentarg++], sizeof(int), PHP_MACHINE_ENDIAN, &ZSTR_VAL(output)[outputpos]); outputpos += sizeof(int); } break; @@ -545,16 +536,16 @@ PHP_FUNCTION(pack) case 'L': case 'N': case 'V': { - int *map = machine_endian_long_map; + php_pack_endianness endianness = PHP_MACHINE_ENDIAN; if (code == 'N') { - map = big_endian_long_map; + endianness = PHP_BIG_ENDIAN; } else if (code == 'V') { - map = little_endian_long_map; + endianness = PHP_LITTLE_ENDIAN; } while (arg-- > 0) { - php_pack(&argv[currentarg++], 4, map, &ZSTR_VAL(output)[outputpos]); + php_pack(&argv[currentarg++], 4, endianness, &ZSTR_VAL(output)[outputpos]); outputpos += 4; } break; @@ -565,16 +556,16 @@ PHP_FUNCTION(pack) case 'Q': case 'J': case 'P': { - int *map = machine_endian_longlong_map; + php_pack_endianness endianness = PHP_MACHINE_ENDIAN; if (code == 'J') { - map = big_endian_longlong_map; + endianness = PHP_BIG_ENDIAN; } else if (code == 'P') { - map = little_endian_longlong_map; + endianness = PHP_LITTLE_ENDIAN; } while (arg-- > 0) { - php_pack(&argv[currentarg++], 8, map, &ZSTR_VAL(output)[outputpos]); + php_pack(&argv[currentarg++], 8, endianness, &ZSTR_VAL(output)[outputpos]); outputpos += 8; } break; @@ -1178,127 +1169,3 @@ PHP_FUNCTION(unpack) } } /* }}} */ - -/* {{{ PHP_MINIT_FUNCTION */ -PHP_MINIT_FUNCTION(pack) -{ - int i; - - if (MACHINE_LITTLE_ENDIAN) { - /* Where to get lo to hi bytes from */ - byte_map[0] = 0; - - for (i = 0; i < (int)sizeof(int); i++) { - int_map[i] = i; - } - - machine_endian_short_map[0] = 0; - machine_endian_short_map[1] = 1; - big_endian_short_map[0] = 1; - big_endian_short_map[1] = 0; - little_endian_short_map[0] = 0; - little_endian_short_map[1] = 1; - - machine_endian_long_map[0] = 0; - machine_endian_long_map[1] = 1; - machine_endian_long_map[2] = 2; - machine_endian_long_map[3] = 3; - big_endian_long_map[0] = 3; - big_endian_long_map[1] = 2; - big_endian_long_map[2] = 1; - big_endian_long_map[3] = 0; - little_endian_long_map[0] = 0; - little_endian_long_map[1] = 1; - little_endian_long_map[2] = 2; - little_endian_long_map[3] = 3; - -#if SIZEOF_ZEND_LONG > 4 - machine_endian_longlong_map[0] = 0; - machine_endian_longlong_map[1] = 1; - machine_endian_longlong_map[2] = 2; - machine_endian_longlong_map[3] = 3; - machine_endian_longlong_map[4] = 4; - machine_endian_longlong_map[5] = 5; - machine_endian_longlong_map[6] = 6; - machine_endian_longlong_map[7] = 7; - big_endian_longlong_map[0] = 7; - big_endian_longlong_map[1] = 6; - big_endian_longlong_map[2] = 5; - big_endian_longlong_map[3] = 4; - big_endian_longlong_map[4] = 3; - big_endian_longlong_map[5] = 2; - big_endian_longlong_map[6] = 1; - big_endian_longlong_map[7] = 0; - little_endian_longlong_map[0] = 0; - little_endian_longlong_map[1] = 1; - little_endian_longlong_map[2] = 2; - little_endian_longlong_map[3] = 3; - little_endian_longlong_map[4] = 4; - little_endian_longlong_map[5] = 5; - little_endian_longlong_map[6] = 6; - little_endian_longlong_map[7] = 7; -#endif - } - else { - zval val; - int size = sizeof(Z_LVAL(val)); - Z_LVAL(val)=0; /*silence a warning*/ - - /* Where to get hi to lo bytes from */ - byte_map[0] = size - 1; - - for (i = 0; i < (int)sizeof(int); i++) { - int_map[i] = size - (sizeof(int) - i); - } - - machine_endian_short_map[0] = size - 2; - machine_endian_short_map[1] = size - 1; - big_endian_short_map[0] = size - 2; - big_endian_short_map[1] = size - 1; - little_endian_short_map[0] = size - 1; - little_endian_short_map[1] = size - 2; - - machine_endian_long_map[0] = size - 4; - machine_endian_long_map[1] = size - 3; - machine_endian_long_map[2] = size - 2; - machine_endian_long_map[3] = size - 1; - big_endian_long_map[0] = size - 4; - big_endian_long_map[1] = size - 3; - big_endian_long_map[2] = size - 2; - big_endian_long_map[3] = size - 1; - little_endian_long_map[0] = size - 1; - little_endian_long_map[1] = size - 2; - little_endian_long_map[2] = size - 3; - little_endian_long_map[3] = size - 4; - -#if SIZEOF_ZEND_LONG > 4 - machine_endian_longlong_map[0] = size - 8; - machine_endian_longlong_map[1] = size - 7; - machine_endian_longlong_map[2] = size - 6; - machine_endian_longlong_map[3] = size - 5; - machine_endian_longlong_map[4] = size - 4; - machine_endian_longlong_map[5] = size - 3; - machine_endian_longlong_map[6] = size - 2; - machine_endian_longlong_map[7] = size - 1; - big_endian_longlong_map[0] = size - 8; - big_endian_longlong_map[1] = size - 7; - big_endian_longlong_map[2] = size - 6; - big_endian_longlong_map[3] = size - 5; - big_endian_longlong_map[4] = size - 4; - big_endian_longlong_map[5] = size - 3; - big_endian_longlong_map[6] = size - 2; - big_endian_longlong_map[7] = size - 1; - little_endian_longlong_map[0] = size - 1; - little_endian_longlong_map[1] = size - 2; - little_endian_longlong_map[2] = size - 3; - little_endian_longlong_map[3] = size - 4; - little_endian_longlong_map[4] = size - 5; - little_endian_longlong_map[5] = size - 6; - little_endian_longlong_map[6] = size - 7; - little_endian_longlong_map[7] = size - 8; -#endif - } - - return SUCCESS; -} -/* }}} */ diff --git a/ext/standard/password.c b/ext/standard/password.c index 1e647bb301c3b..99dea810806cd 100644 --- a/ext/standard/password.c +++ b/ext/standard/password.c @@ -86,18 +86,18 @@ static zend_string* php_password_make_salt(size_t length) /* {{{ */ buffer = zend_string_alloc(length * 3 / 4 + 1, 0); if (FAILURE == php_random_bytes_throw(ZSTR_VAL(buffer), ZSTR_LEN(buffer))) { zend_value_error("Unable to generate salt"); - zend_string_release_ex(buffer, 0); + zend_string_efree(buffer); return NULL; } ret = zend_string_alloc(length, 0); if (php_password_salt_to64(ZSTR_VAL(buffer), ZSTR_LEN(buffer), length, ZSTR_VAL(ret)) == FAILURE) { zend_value_error("Generated salt too short"); - zend_string_release_ex(buffer, 0); - zend_string_release_ex(ret, 0); + zend_string_efree(buffer); + zend_string_efree(ret); return NULL; } - zend_string_release_ex(buffer, 0); + zend_string_efree(buffer); ZSTR_VAL(ret)[length] = 0; return ret; } diff --git a/ext/standard/password.stub.php b/ext/standard/password.stub.php index c3c99117d514c..b4758ef54b126 100644 --- a/ext/standard/password.stub.php +++ b/ext/standard/password.stub.php @@ -2,13 +2,7 @@ /** @generate-class-entries */ -/** - * @var string - */ const PASSWORD_DEFAULT = "2y"; -/** - * @var string - */ const PASSWORD_BCRYPT = "2y"; /** * @var int @@ -17,17 +11,8 @@ const PASSWORD_BCRYPT_DEFAULT_COST = UNKNOWN; #ifdef HAVE_ARGON2LIB -/** - * @var string - */ const PASSWORD_ARGON2I = "argon2i"; -/** - * @var string - */ const PASSWORD_ARGON2ID = "argon2id"; -/** - * @var string - */ const PASSWORD_ARGON2_PROVIDER = "standard"; /** * @var int diff --git a/ext/standard/password_arginfo.h b/ext/standard/password_arginfo.h index fd25fbed67739..ec4876fe2a3cc 100644 --- a/ext/standard/password_arginfo.h +++ b/ext/standard/password_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: aab38646ace967e985c348b78251474693da95a7 */ + * Stub hash: f61df8d477588718e0eb1b055e5a3e138e6bcad3 */ static void register_password_symbols(int module_number) { diff --git a/ext/standard/php_image.h b/ext/standard/php_image.h index a41273e6745ae..6a4e0987d13db 100644 --- a/ext/standard/php_image.h +++ b/ext/standard/php_image.h @@ -18,6 +18,9 @@ #ifndef PHP_IMAGE_H #define PHP_IMAGE_H +PHP_MINIT_FUNCTION(image); +PHP_MSHUTDOWN_FUNCTION(image); + /* {{{ enum image_filetype This enum is used to have ext/standard/image.c and ext/exif/exif.c use the same constants for file types. @@ -44,15 +47,44 @@ typedef enum IMAGE_FILETYPE_ICO, IMAGE_FILETYPE_WEBP, IMAGE_FILETYPE_AVIF, + IMAGE_FILETYPE_HEIF, /* WHEN EXTENDING: PLEASE ALSO REGISTER IN basic_function.stub.php */ - IMAGE_FILETYPE_COUNT + IMAGE_FILETYPE_FIXED_COUNT } image_filetype; /* }}} */ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetype); -PHPAPI char * php_image_type_to_mime_type(int image_type); +PHPAPI const char * php_image_type_to_mime_type(int image_type); PHPAPI bool php_is_image_avif(php_stream *stream); +/* return info as a struct, to make expansion easier */ +struct php_gfxinfo { + unsigned int width; + unsigned int height; + zend_string *width_unit; + zend_string *height_unit; + unsigned int bits; + unsigned int channels; +}; + +typedef zend_result (*php_image_identify)(php_stream *stream); +typedef struct php_gfxinfo *(*php_image_get_info)(php_stream *stream); + +struct php_image_handler { + const char *mime_type; + const char *extension; + const char *const_name; + php_image_identify identify; + php_image_get_info get_info; +}; + +#define PHP_IMAGE_CONST_NAME(suffix) ("IMAGETYPE_" suffix) + +/* This should only be called on module init */ +PHPAPI int php_image_register_handler(const struct php_image_handler *handler); +/* This should only be called on module shutdown */ +PHPAPI zend_result php_image_unregister_handler(int image_type); + #endif /* PHP_IMAGE_H */ diff --git a/ext/standard/php_standard.h b/ext/standard/php_standard.h index 78eba25f11a58..5bc792362bbd2 100644 --- a/ext/standard/php_standard.h +++ b/ext/standard/php_standard.h @@ -29,7 +29,6 @@ #include "php_ext_syslog.h" #include "php_filestat.h" #include "php_browscap.h" -#include "pack.h" #include "url.h" #include "pageinfo.h" #include "fsock.h" diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 06a3f916a849c..690e23e0d3538 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -136,11 +136,11 @@ int openpty(int *master, int *slave, char *name, struct termios *termp, struct w static int le_proc_open; /* Resource number for `proc` resources */ -/* {{{ _php_array_to_envp +/* {{{ php_array_to_envp * Process the `environment` argument to `proc_open` * Convert into data structures which can be passed to underlying OS APIs like `exec` on POSIX or * `CreateProcessW` on Win32 */ -static php_process_env _php_array_to_envp(zval *environment) +ZEND_ATTRIBUTE_NONNULL static php_process_env php_array_to_envp(const HashTable *environment) { zval *element; php_process_env env; @@ -154,13 +154,9 @@ static php_process_env _php_array_to_envp(zval *environment) memset(&env, 0, sizeof(env)); - if (!environment) { - return env; - } - - uint32_t cnt = zend_hash_num_elements(Z_ARRVAL_P(environment)); + uint32_t cnt = zend_hash_num_elements(environment); - if (cnt < 1) { + if (cnt == 0) { #ifndef PHP_WIN32 env.envarray = (char **) ecalloc(1, sizeof(char *)); #endif @@ -172,7 +168,7 @@ static php_process_env _php_array_to_envp(zval *environment) zend_hash_init(env_hash, cnt, NULL, NULL, 0); /* first, we have to get the size of all the elements in the hash */ - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(environment), key, element) { + ZEND_HASH_FOREACH_STR_KEY_VAL(environment, key, element) { str = zval_get_string(element); if (ZSTR_LEN(str) == 0) { @@ -221,7 +217,7 @@ static php_process_env _php_array_to_envp(zval *environment) /* }}} */ /* {{{ _php_free_envp - * Free the structures allocated by `_php_array_to_envp` */ + * Free the structures allocated by php_array_to_envp */ static void _php_free_envp(php_process_env env) { #ifndef PHP_WIN32 @@ -506,7 +502,7 @@ typedef struct _descriptorspec_item { int mode_flags; /* mode for opening FDs: r/o, r/w, binary (on Win32), etc */ } descriptorspec_item; -static zend_string *get_valid_arg_string(zval *zv, int elem_num) { +static zend_string *get_valid_arg_string(zval *zv, uint32_t elem_num) { zend_string *str = zval_get_string(zv); if (!str) { return NULL; @@ -518,7 +514,7 @@ static zend_string *get_valid_arg_string(zval *zv, int elem_num) { return NULL; } - if (strlen(ZSTR_VAL(str)) != ZSTR_LEN(str)) { + if (zend_str_has_nul_byte(str)) { zend_value_error("Command array element %d contains a null byte", elem_num); zend_string_release(str); return NULL; @@ -630,7 +626,7 @@ static zend_string *create_win_command_from_args(HashTable *args) zval *arg_zv; bool is_prog_name = true; bool is_cmd_execution = false; - int elem_num = 0; + uint32_t elem_num = 0; ZEND_HASH_FOREACH_VAL(args, arg_zv) { zend_string *arg_str = get_valid_arg_string(arg_zv, ++elem_num); @@ -778,11 +774,11 @@ static zend_result convert_command_to_use_shell(wchar_t **cmdw, size_t cmdw_len) #ifndef PHP_WIN32 /* Convert command parameter array passed as first argument to `proc_open` into command string */ -static zend_string* get_command_from_array(HashTable *array, char ***argv, int num_elems) +static zend_string* get_command_from_array(const HashTable *array, char ***argv, uint32_t num_elems) { zval *arg_zv; zend_string *command = NULL; - int i = 0; + uint32_t i = 0; *argv = safe_emalloc(sizeof(char *), num_elems + 1, 0); @@ -810,16 +806,16 @@ static zend_string* get_command_from_array(HashTable *array, char ***argv, int n } #endif -static descriptorspec_item* alloc_descriptor_array(HashTable *descriptorspec) +static descriptorspec_item* alloc_descriptor_array(const HashTable *descriptorspec) { uint32_t ndescriptors = zend_hash_num_elements(descriptorspec); return ecalloc(ndescriptors, sizeof(descriptorspec_item)); } -static zend_string* get_string_parameter(zval *array, int index, char *param_name) +static zend_string* get_string_parameter(const HashTable *ht, unsigned int index, const char *param_name) { zval *array_item; - if ((array_item = zend_hash_index_find(Z_ARRVAL_P(array), index)) == NULL) { + if ((array_item = zend_hash_index_find(ht, index)) == NULL) { zend_value_error("Missing %s", param_name); return NULL; } @@ -995,7 +991,7 @@ static zend_result dup_proc_descriptor(php_file_descriptor_t from, php_file_desc } static zend_result redirect_proc_descriptor(descriptorspec_item *desc, int target, - descriptorspec_item *descriptors, int ndesc, int nindex) + const descriptorspec_item *descriptors, int ndesc, int nindex) { php_file_descriptor_t redirect_to = PHP_INVALID_FD; @@ -1030,9 +1026,9 @@ static zend_result redirect_proc_descriptor(descriptorspec_item *desc, int targe } /* Process one item from `$descriptorspec` argument to `proc_open` */ -static zend_result set_proc_descriptor_from_array(zval *descitem, descriptorspec_item *descriptors, +static zend_result set_proc_descriptor_from_array(const HashTable *ht, descriptorspec_item *descriptors, int ndesc, int nindex, int *pty_master_fd, int *pty_slave_fd) { - zend_string *ztype = get_string_parameter(descitem, 0, "handle qualifier"); + zend_string *ztype = get_string_parameter(ht, 0, "handle qualifier"); if (!ztype) { return FAILURE; } @@ -1042,7 +1038,7 @@ static zend_result set_proc_descriptor_from_array(zval *descitem, descriptorspec if (zend_string_equals_literal(ztype, "pipe")) { /* Set descriptor to pipe */ - zmode = get_string_parameter(descitem, 1, "mode parameter for 'pipe'"); + zmode = get_string_parameter(ht, 1, "mode parameter for 'pipe'"); if (zmode == NULL) { goto finish; } @@ -1052,16 +1048,16 @@ static zend_result set_proc_descriptor_from_array(zval *descitem, descriptorspec retval = set_proc_descriptor_to_socket(&descriptors[ndesc]); } else if (zend_string_equals(ztype, ZSTR_KNOWN(ZEND_STR_FILE))) { /* Set descriptor to file */ - if ((zfile = get_string_parameter(descitem, 1, "file name parameter for 'file'")) == NULL) { + if ((zfile = get_string_parameter(ht, 1, "file name parameter for 'file'")) == NULL) { goto finish; } - if ((zmode = get_string_parameter(descitem, 2, "mode parameter for 'file'")) == NULL) { + if ((zmode = get_string_parameter(ht, 2, "mode parameter for 'file'")) == NULL) { goto finish; } retval = set_proc_descriptor_to_file(&descriptors[ndesc], zfile, zmode); } else if (zend_string_equals_literal(ztype, "redirect")) { /* Redirect descriptor to whatever another descriptor is set to */ - zval *ztarget = zend_hash_index_find_deref(Z_ARRVAL_P(descitem), 1); + zval *ztarget = zend_hash_index_find_deref(ht, 1); if (!ztarget) { zend_value_error("Missing redirection target"); goto finish; @@ -1116,7 +1112,7 @@ static zend_result set_proc_descriptor_from_resource(zval *resource, descriptors #ifndef PHP_WIN32 #if defined(USE_POSIX_SPAWN) -static zend_result close_parentends_of_pipes(posix_spawn_file_actions_t * actions, descriptorspec_item *descriptors, int ndesc) +static zend_result close_parentends_of_pipes(posix_spawn_file_actions_t * actions, const descriptorspec_item *descriptors, int ndesc) { int r; for (int i = 0; i < ndesc; i++) { @@ -1200,9 +1196,10 @@ PHP_FUNCTION(proc_open) HashTable *command_ht; HashTable *descriptorspec; /* Mandatory argument */ zval *pipes; /* Mandatory argument */ - char *cwd = NULL; /* Optional argument */ - size_t cwd_len = 0; /* Optional argument */ - zval *environment = NULL, *other_options = NULL; /* Optional arguments */ + char *cwd = NULL; /* Optional argument */ + size_t cwd_len = 0; /* Optional argument */ + HashTable *environment = NULL; /* Optional arguments */ + zval *other_options = NULL; /* Optional arguments */ php_process_env env; int ndesc = 0; @@ -1239,7 +1236,7 @@ PHP_FUNCTION(proc_open) Z_PARAM_ZVAL(pipes) Z_PARAM_OPTIONAL Z_PARAM_STRING_OR_NULL(cwd, cwd_len) - Z_PARAM_ARRAY_OR_NULL(environment) + Z_PARAM_ARRAY_HT_OR_NULL(environment) Z_PARAM_ARRAY_OR_NULL(other_options) ZEND_PARSE_PARAMETERS_END(); @@ -1282,7 +1279,7 @@ PHP_FUNCTION(proc_open) #endif if (environment) { - env = _php_array_to_envp(environment); + env = php_array_to_envp(environment); } descriptors = alloc_descriptor_array(descriptorspec); @@ -1302,7 +1299,7 @@ PHP_FUNCTION(proc_open) goto exit_fail; } } else if (Z_TYPE_P(descitem) == IS_ARRAY) { - if (set_proc_descriptor_from_array(descitem, descriptors, ndesc, (int)nindex, + if (set_proc_descriptor_from_array(Z_ARRVAL_P(descitem), descriptors, ndesc, (int)nindex, &pty_master_fd, &pty_slave_fd) == FAILURE) { goto exit_fail; } diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 818a645086b05..506ce0dafed8b 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -99,7 +99,6 @@ PHP_FUNCTION(stream_socket_client) zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL; double timeout; bool timeout_is_null = 1; - php_timeout_ull conv; struct timeval tv; char *hashkey = NULL; php_stream *stream = NULL; @@ -138,7 +137,7 @@ PHP_FUNCTION(stream_socket_client) if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) { tv_pointer = NULL; } else { - conv = (php_timeout_ull) (timeout * 1000000.0); + php_timeout_ull conv = (php_timeout_ull) (timeout * 1000000.0); #ifdef PHP_WIN32 tv.tv_sec = (long)(conv / 1000000); tv.tv_usec = (long)(conv % 1000000); @@ -262,7 +261,6 @@ PHP_FUNCTION(stream_socket_accept) bool timeout_is_null = 1; zval *zpeername = NULL; zend_string *peername = NULL; - php_timeout_ull conv; struct timeval tv; php_stream *stream = NULL, *clistream = NULL; zend_string *errstr = NULL; @@ -286,7 +284,7 @@ PHP_FUNCTION(stream_socket_accept) if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) { tv_pointer = NULL; } else { - conv = (php_timeout_ull) (timeout * 1000000.0); + php_timeout_ull conv = (php_timeout_ull) (timeout * 1000000.0); #ifdef PHP_WIN32 tv.tv_sec = (long)(conv / 1000000); tv.tv_usec = (long)(conv % 1000000); @@ -484,7 +482,6 @@ PHP_FUNCTION(stream_copy_to_stream) zend_long maxlen, pos = 0; bool maxlen_is_null = 1; size_t len; - int ret; ZEND_PARSE_PARAMETERS_START(2, 4) PHP_Z_PARAM_STREAM(src) @@ -503,9 +500,7 @@ PHP_FUNCTION(stream_copy_to_stream) RETURN_FALSE; } - ret = php_stream_copy_to_stream_ex(src, dest, maxlen, &len); - - if (ret != SUCCESS) { + if (php_stream_copy_to_stream_ex(src, dest, maxlen, &len) != SUCCESS) { RETURN_FALSE; } RETURN_LONG(len); @@ -534,9 +529,9 @@ PHP_FUNCTION(stream_get_meta_data) add_assoc_zval(return_value, "wrapper_data", &stream->wrapperdata); } if (stream->wrapper) { - add_assoc_string(return_value, "wrapper_type", (char *)stream->wrapper->wops->label); + add_assoc_string(return_value, "wrapper_type", stream->wrapper->wops->label); } - add_assoc_string(return_value, "stream_type", (char *)stream->ops->label); + add_assoc_string(return_value, "stream_type", stream->ops->label); add_assoc_string(return_value, "mode", stream->mode); @@ -548,7 +543,7 @@ PHP_FUNCTION(stream_get_meta_data) array_init(newval); for (filter = stream->filterhead; filter != NULL; filter = filter->next) { - add_next_index_string(newval, (char *)filter->fops->label); + add_next_index_string(newval, filter->fops->label); } add_assoc_zval(return_value, "filters", newval); @@ -568,13 +563,13 @@ PHP_FUNCTION(stream_get_meta_data) /* {{{ Retrieves list of registered socket transports */ PHP_FUNCTION(stream_get_transports) { - HashTable *stream_xport_hash; - zend_string *stream_xport; ZEND_PARSE_PARAMETERS_NONE(); - stream_xport_hash = php_stream_xport_get_hash(); array_init(return_value); + + const HashTable *stream_xport_hash = php_stream_xport_get_hash(); + zend_string *stream_xport; ZEND_HASH_MAP_FOREACH_STR_KEY(stream_xport_hash, stream_xport) { add_next_index_str(return_value, zend_string_copy(stream_xport)); } ZEND_HASH_FOREACH_END(); @@ -584,13 +579,12 @@ PHP_FUNCTION(stream_get_transports) /* {{{ Retrieves list of registered stream wrappers */ PHP_FUNCTION(stream_get_wrappers) { - HashTable *url_stream_wrappers_hash; - zend_string *stream_protocol; - ZEND_PARSE_PARAMETERS_NONE(); - url_stream_wrappers_hash = php_stream_get_url_stream_wrappers_hash(); array_init(return_value); + + const HashTable *url_stream_wrappers_hash = php_stream_get_url_stream_wrappers_hash(); + zend_string *stream_protocol; ZEND_HASH_MAP_FOREACH_STR_KEY(url_stream_wrappers_hash, stream_protocol) { if (stream_protocol) { add_next_index_str(return_value, zend_string_copy(stream_protocol)); @@ -601,17 +595,13 @@ PHP_FUNCTION(stream_get_wrappers) /* }}} */ /* {{{ stream_select related functions */ -static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t *max_fd) +static int stream_array_to_fd_set(const HashTable *stream_array, fd_set *fds, php_socket_t *max_fd) { zval *elem; php_stream *stream; int cnt = 0; - if (Z_TYPE_P(stream_array) != IS_ARRAY) { - return 0; - } - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(stream_array), elem) { + ZEND_HASH_FOREACH_VAL(stream_array, elem) { /* Temporary int fd is needed for the STREAM data type on windows, passing this_fd directly to php_stream_cast() would eventually bring a wrong result on x64. php_stream_cast() casts to int internally, and this will leave the higher bits of a SOCKET variable uninitialized on systems with little endian. */ @@ -640,7 +630,7 @@ static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t return cnt ? 1 : 0; } -static int stream_array_from_fd_set(zval *stream_array, fd_set *fds) +static int stream_array_from_fd_set(zval *stream_array, const fd_set *fds) { zval *elem, *dest_elem; HashTable *ht; @@ -649,9 +639,7 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds) zend_string *key; zend_ulong num_ind; - if (Z_TYPE_P(stream_array) != IS_ARRAY) { - return 0; - } + ZEND_ASSERT(Z_TYPE_P(stream_array) == IS_ARRAY); ht = zend_new_array(zend_hash_num_elements(Z_ARRVAL_P(stream_array))); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(stream_array), num_ind, key, elem) { @@ -677,7 +665,6 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds) zval_add_ref(dest_elem); ret++; - continue; } } } ZEND_HASH_FOREACH_END(); @@ -698,9 +685,7 @@ static int stream_array_emulate_read_fd_set(zval *stream_array) zend_ulong num_ind; zend_string *key; - if (Z_TYPE_P(stream_array) != IS_ARRAY) { - return 0; - } + ZEND_ASSERT(Z_TYPE_P(stream_array) == IS_ARRAY); ht = zend_new_array(zend_hash_num_elements(Z_ARRVAL_P(stream_array))); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(stream_array), num_ind, key, elem) { @@ -723,7 +708,6 @@ static int stream_array_emulate_read_fd_set(zval *stream_array) } zval_add_ref(dest_elem); ret++; - continue; } } ZEND_HASH_FOREACH_END(); @@ -766,21 +750,21 @@ PHP_FUNCTION(stream_select) FD_ZERO(&efds); if (r_array != NULL) { - set_count = stream_array_to_fd_set(r_array, &rfds, &max_fd); + set_count = stream_array_to_fd_set(Z_ARR_P(r_array), &rfds, &max_fd); if (set_count > max_set_count) max_set_count = set_count; sets += set_count; } if (w_array != NULL) { - set_count = stream_array_to_fd_set(w_array, &wfds, &max_fd); + set_count = stream_array_to_fd_set(Z_ARR_P(w_array), &wfds, &max_fd); if (set_count > max_set_count) max_set_count = set_count; sets += set_count; } if (e_array != NULL) { - set_count = stream_array_to_fd_set(e_array, &efds, &max_fd); + set_count = stream_array_to_fd_set(Z_ARR_P(e_array), &efds, &max_fd); if (set_count > max_set_count) max_set_count = set_count; sets += set_count; @@ -856,10 +840,7 @@ PHP_FUNCTION(stream_select) static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity, char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr) { - zval *callback = &context->notifier->ptr; - zval retval; zval zvs[6]; - int i; ZVAL_LONG(&zvs[0], notifycode); ZVAL_LONG(&zvs[1], severity); @@ -872,24 +853,20 @@ static void user_space_stream_notifier(php_stream_context *context, int notifyco ZVAL_LONG(&zvs[4], bytes_sofar); ZVAL_LONG(&zvs[5], bytes_max); - if (FAILURE == call_user_function(NULL, NULL, callback, &retval, 6, zvs)) { - php_error_docref(NULL, E_WARNING, "Failed to call user notifier"); - } - for (i = 0; i < 6; i++) { - zval_ptr_dtor(&zvs[i]); - } - zval_ptr_dtor(&retval); + zend_call_known_fcc(context->notifier->ptr, NULL, 6, zvs, NULL); + /* Free refcounted string parameter */ + zval_ptr_dtor_str(&zvs[2]); } static void user_space_stream_notifier_dtor(php_stream_notifier *notifier) { - if (notifier && Z_TYPE(notifier->ptr) != IS_UNDEF) { - zval_ptr_dtor(¬ifier->ptr); - ZVAL_UNDEF(¬ifier->ptr); - } + zend_fcall_info_cache *fcc = notifier->ptr; + zend_fcc_dtor(fcc); + efree(notifier->ptr); + notifier->ptr = NULL; } -static zend_result parse_context_options(php_stream_context *context, HashTable *options) +static zend_result parse_context_options(php_stream_context *context, const HashTable *options) { zval *wval, *oval; zend_string *wkey, *okey; @@ -913,7 +890,7 @@ static zend_result parse_context_options(php_stream_context *context, HashTable return SUCCESS; } -static zend_result parse_context_params(php_stream_context *context, HashTable *params) +static zend_result parse_context_params(php_stream_context *context, const HashTable *params) { zval *tmp; @@ -924,9 +901,19 @@ static zend_result parse_context_params(php_stream_context *context, HashTable * context->notifier = NULL; } + zend_fcall_info_cache *fcc = emalloc(sizeof(*fcc)); + char *error; + if (!zend_is_callable_ex(tmp, NULL, 0, NULL, fcc, &error)) { + zend_argument_type_error(1, "must be an array with valid callbacks as values, %s", error); + efree(fcc); + efree(error); + return FAILURE; + } + zend_fcc_addref(fcc); + context->notifier = php_stream_notification_alloc(); context->notifier->func = user_space_stream_notifier; - ZVAL_COPY(&context->notifier->ptr, tmp); + context->notifier->ptr = fcc; context->notifier->dtor = user_space_stream_notifier_dtor; } if (NULL != (tmp = zend_hash_str_find(params, "options", sizeof("options")-1))) { @@ -1123,9 +1110,11 @@ PHP_FUNCTION(stream_context_get_params) } array_init(return_value); - if (context->notifier && Z_TYPE(context->notifier->ptr) != IS_UNDEF && context->notifier->func == user_space_stream_notifier) { - Z_TRY_ADDREF(context->notifier->ptr); - add_assoc_zval_ex(return_value, "notification", sizeof("notification")-1, &context->notifier->ptr); + if (context->notifier && context->notifier->func == user_space_stream_notifier) { + zend_fcall_info_cache *fcc = context->notifier->ptr; + zval fn; + zend_get_callable_zval_from_fcc(fcc, &fn); + add_assoc_zval_ex(return_value, ZEND_STRL("notification"), &fn); } Z_TRY_ADDREF(context->options); add_assoc_zval_ex(return_value, "options", sizeof("options")-1, &context->options); @@ -1213,7 +1202,7 @@ PHP_FUNCTION(stream_context_create) /* }}} */ /* {{{ streams filter functions */ -static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) +static void apply_filter_to_stream(bool append, INTERNAL_FUNCTION_PARAMETERS) { php_stream *stream; char *filtername; @@ -1221,7 +1210,6 @@ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) zend_long read_write = 0; zval *filterparams = NULL; php_stream_filter *filter = NULL; - int ret; ZEND_PARSE_PARAMETERS_START(2, 4) PHP_Z_PARAM_STREAM(stream) @@ -1252,13 +1240,13 @@ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) } if (append) { - ret = php_stream_filter_append_ex(&stream->readfilters, filter); + zend_result ret = php_stream_filter_append_ex(&stream->readfilters, filter); + if (ret != SUCCESS) { + php_stream_filter_remove(filter, 1); + RETURN_FALSE; + } } else { - ret = php_stream_filter_prepend_ex(&stream->readfilters, filter); - } - if (ret != SUCCESS) { - php_stream_filter_remove(filter, 1); - RETURN_FALSE; + php_stream_filter_prepend_ex(&stream->readfilters, filter); } } @@ -1269,13 +1257,13 @@ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) } if (append) { - ret = php_stream_filter_append_ex(&stream->writefilters, filter); + zend_result ret = php_stream_filter_append_ex(&stream->writefilters, filter); + if (ret != SUCCESS) { + php_stream_filter_remove(filter, 1); + RETURN_FALSE; + } } else { - ret = php_stream_filter_prepend_ex(&stream->writefilters, filter); - } - if (ret != SUCCESS) { - php_stream_filter_remove(filter, 1); - RETURN_FALSE; + php_stream_filter_prepend_ex(&stream->writefilters, filter); } } @@ -1373,11 +1361,7 @@ PHP_FUNCTION(stream_set_blocking) Z_PARAM_BOOL(block) ZEND_PARSE_PARAMETERS_END(); - if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, block, NULL) == -1) { - RETURN_FALSE; - } - - RETURN_TRUE; + RETURN_BOOL(-1 != php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, block, NULL)); } /* }}} */ @@ -1418,11 +1402,7 @@ PHP_FUNCTION(stream_set_timeout) } #endif - if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &t)) { - RETURN_TRUE; - } - - RETURN_FALSE; + RETURN_BOOL(PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &t)); } #endif /* HAVE_SYS_TIME_H || defined(PHP_WIN32) */ /* }}} */ @@ -1598,11 +1578,7 @@ PHP_FUNCTION(stream_is_local) wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(zstream), NULL, 0); } - if (!wrapper) { - RETURN_FALSE; - } - - RETURN_BOOL(wrapper->is_url==0); + RETURN_BOOL(wrapper && wrapper->is_url == 0); } /* }}} */ @@ -1615,11 +1591,7 @@ PHP_FUNCTION(stream_supports_lock) PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - if (!php_stream_supports_lock(stream)) { - RETURN_FALSE; - } - - RETURN_TRUE; + RETURN_BOOL(php_stream_supports_lock(stream)); } /* {{{ Check if a stream is a TTY. */ @@ -1646,15 +1618,13 @@ PHP_FUNCTION(stream_isatty) #ifdef PHP_WIN32 /* Check if the Windows standard handle is redirected to file */ - RETVAL_BOOL(php_win32_console_fileno_is_console(fileno)); + RETURN_BOOL(php_win32_console_fileno_is_console(fileno)); #elif defined(HAVE_UNISTD_H) /* Check if the file descriptor identifier is a terminal */ - RETVAL_BOOL(isatty(fileno)); + RETURN_BOOL(isatty(fileno)); #else - { - zend_stat_t stat = {0}; - RETVAL_BOOL(zend_fstat(fileno, &stat) == 0 && (stat.st_mode & /*S_IFMT*/0170000) == /*S_IFCHR*/0020000); - } + zend_stat_t stat = {0}; + RETURN_BOOL(zend_fstat(fileno, &stat) == 0 && (stat.st_mode & /*S_IFMT*/0170000) == /*S_IFCHR*/0020000); #endif } @@ -1700,21 +1670,10 @@ PHP_FUNCTION(sapi_windows_vt100_support) if (enable_is_null) { /* Check if the Windows standard handle has VT100 control codes enabled */ - if (php_win32_console_fileno_has_vt100(fileno)) { - RETURN_TRUE; - } - else { - RETURN_FALSE; - } - } - else { + RETURN_BOOL(php_win32_console_fileno_has_vt100(fileno)); + } else { /* Enable/disable VT100 control codes support for the specified Windows standard handle */ - if (php_win32_console_fileno_set_vt100(fileno, enable ? TRUE : FALSE)) { - RETURN_TRUE; - } - else { - RETURN_FALSE; - } + RETURN_BOOL(php_win32_console_fileno_set_vt100(fileno, enable ? TRUE : FALSE)); } } #endif diff --git a/ext/standard/string.c b/ext/standard/string.c index 36903b3c5c7b9..8b76a179061cc 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1026,7 +1026,11 @@ PHPAPI void php_implode(const zend_string *glue, HashTable *pieces, zval *return } cptr -= ZSTR_LEN(glue); - memcpy(cptr, ZSTR_VAL(glue), ZSTR_LEN(glue)); + if (ZSTR_LEN(glue) == 1) { + *cptr = ZSTR_VAL(glue)[0]; + } else { + memcpy(cptr, ZSTR_VAL(glue), ZSTR_LEN(glue)); + } } free_alloca(strings, use_heap); @@ -2404,7 +2408,7 @@ PHP_FUNCTION(substr_replace) if (repl_idx < repl_ht->nNumUsed) { repl_str = zval_get_tmp_string(tmp_repl, &tmp_repl_str); } else { - repl_str = STR_EMPTY_ALLOC(); + repl_str = ZSTR_EMPTY_ALLOC(); } } @@ -2651,6 +2655,15 @@ PHP_FUNCTION(ord) Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); + if (UNEXPECTED(ZSTR_LEN(str) != 1)) { + if (ZSTR_LEN(str) == 0) { + php_error_docref(NULL, E_DEPRECATED, + "Providing an empty string is deprecated"); + } else { + php_error_docref(NULL, E_DEPRECATED, + "Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead"); + } + } RETURN_LONG((unsigned char) ZSTR_VAL(str)[0]); } /* }}} */ @@ -2665,6 +2678,12 @@ PHP_FUNCTION(chr) Z_PARAM_LONG(c) ZEND_PARSE_PARAMETERS_END(); + if (UNEXPECTED(c < 0 || c > 255)) { + php_error_docref(NULL, E_DEPRECATED, + "Providing a value not in-between 0 and 255 is deprecated," + " this is because a byte value must be in the [0, 255] interval." + " The value used will be constrained using %% 256"); + } c &= 0xff; RETURN_CHAR(c); } @@ -4937,17 +4956,18 @@ PHP_FUNCTION(setlocale) zend_string **strings = do_alloca(sizeof(zend_string *) * num_args, use_heap); for (uint32_t i = 0; i < num_args; i++) { - if (UNEXPECTED(Z_TYPE(args[i]) != IS_ARRAY && !zend_parse_arg_str(&args[i], &strings[i], false, i + 2))) { + if (UNEXPECTED(Z_TYPE(args[i]) != IS_ARRAY && !zend_parse_arg_str(&args[i], &strings[i], true, i + 2))) { zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING, &args[i]); goto out; } } for (uint32_t i = 0; i < num_args; i++) { + zend_string *result; if (Z_TYPE(args[i]) == IS_ARRAY) { zval *elem; ZEND_HASH_FOREACH_VAL(Z_ARRVAL(args[i]), elem) { - zend_string *result = try_setlocale_zval(cat, elem); + result = try_setlocale_zval(cat, elem); if (EG(exception)) { goto out; } @@ -4956,15 +4976,18 @@ PHP_FUNCTION(setlocale) goto out; } } ZEND_HASH_FOREACH_END(); + continue; + } else if (Z_ISNULL(args[i])) { + result = try_setlocale_str(cat, ZSTR_EMPTY_ALLOC()); } else { - zend_string *result = try_setlocale_str(cat, strings[i]); - if (EG(exception)) { - goto out; - } - if (result) { - RETVAL_STR(result); - goto out; - } + result = try_setlocale_str(cat, strings[i]); + } + if (EG(exception)) { + goto out; + } + if (result) { + RETVAL_STR(result); + goto out; } } diff --git a/ext/standard/tests/array/array_diff_assoc_variation1.phpt b/ext/standard/tests/array/array_diff_assoc_variation1.phpt deleted file mode 100644 index b16baa300f575..0000000000000 --- a/ext/standard/tests/array/array_diff_assoc_variation1.phpt +++ /dev/null @@ -1,179 +0,0 @@ ---TEST-- -Test array_diff_assoc() function : usage variations - unexpected values for 'array1' argument ---FILE-- -getMessage(), "\n"; - } - $iterator++; -}; -fclose($fp); -echo "Done"; -?> ---EXPECT-- -*** Testing array_diff_assoc() : usage variations *** - --- Iteration 1 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, int given - --- Iteration 2 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, int given - --- Iteration 3 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, int given - --- Iteration 4 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, int given - --- Iteration 5 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, float given - --- Iteration 6 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, float given - --- Iteration 7 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, float given - --- Iteration 8 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, float given - --- Iteration 9 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, float given - --- Iteration 10 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, null given - --- Iteration 11 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, null given - --- Iteration 12 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, true given - --- Iteration 13 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, false given - --- Iteration 14 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, true given - --- Iteration 15 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, false given - --- Iteration 16 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, string given - --- Iteration 17 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, string given - --- Iteration 18 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, string given - --- Iteration 19 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, string given - --- Iteration 20 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, string given - --- Iteration 21 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, string given - --- Iteration 22 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, string given - --- Iteration 23 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, classA given - --- Iteration 24 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, null given - --- Iteration 25 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, null given - --- Iteration 26 -- -array_diff_assoc(): Argument #1 ($array) must be of type array, resource given -Done diff --git a/ext/standard/tests/array/array_diff_assoc_variation2.phpt b/ext/standard/tests/array/array_diff_assoc_variation2.phpt deleted file mode 100644 index a0b1bac329d9a..0000000000000 --- a/ext/standard/tests/array/array_diff_assoc_variation2.phpt +++ /dev/null @@ -1,179 +0,0 @@ ---TEST-- -Test array_diff_assoc() function : usage variations - unexpected values for 'array1' argument ---FILE-- -getMessage(), "\n"; - } - $iterator++; -}; -fclose($fp); -echo "Done"; -?> ---EXPECT-- -*** Testing array_diff_assoc() : usage variations *** - --- Iteration 1 -- -array_diff_assoc(): Argument #2 must be of type array, int given - --- Iteration 2 -- -array_diff_assoc(): Argument #2 must be of type array, int given - --- Iteration 3 -- -array_diff_assoc(): Argument #2 must be of type array, int given - --- Iteration 4 -- -array_diff_assoc(): Argument #2 must be of type array, int given - --- Iteration 5 -- -array_diff_assoc(): Argument #2 must be of type array, float given - --- Iteration 6 -- -array_diff_assoc(): Argument #2 must be of type array, float given - --- Iteration 7 -- -array_diff_assoc(): Argument #2 must be of type array, float given - --- Iteration 8 -- -array_diff_assoc(): Argument #2 must be of type array, float given - --- Iteration 9 -- -array_diff_assoc(): Argument #2 must be of type array, float given - --- Iteration 10 -- -array_diff_assoc(): Argument #2 must be of type array, null given - --- Iteration 11 -- -array_diff_assoc(): Argument #2 must be of type array, null given - --- Iteration 12 -- -array_diff_assoc(): Argument #2 must be of type array, true given - --- Iteration 13 -- -array_diff_assoc(): Argument #2 must be of type array, false given - --- Iteration 14 -- -array_diff_assoc(): Argument #2 must be of type array, true given - --- Iteration 15 -- -array_diff_assoc(): Argument #2 must be of type array, false given - --- Iteration 16 -- -array_diff_assoc(): Argument #2 must be of type array, string given - --- Iteration 17 -- -array_diff_assoc(): Argument #2 must be of type array, string given - --- Iteration 18 -- -array_diff_assoc(): Argument #2 must be of type array, string given - --- Iteration 19 -- -array_diff_assoc(): Argument #2 must be of type array, string given - --- Iteration 20 -- -array_diff_assoc(): Argument #2 must be of type array, string given - --- Iteration 21 -- -array_diff_assoc(): Argument #2 must be of type array, string given - --- Iteration 22 -- -array_diff_assoc(): Argument #2 must be of type array, string given - --- Iteration 23 -- -array_diff_assoc(): Argument #2 must be of type array, classA given - --- Iteration 24 -- -array_diff_assoc(): Argument #2 must be of type array, null given - --- Iteration 25 -- -array_diff_assoc(): Argument #2 must be of type array, null given - --- Iteration 26 -- -array_diff_assoc(): Argument #2 must be of type array, resource given -Done diff --git a/ext/standard/tests/array/array_diff_assoc_variation3.phpt b/ext/standard/tests/array/array_diff_assoc_variation3.phpt index b32e484fd1903..4833725ffe4eb 100644 --- a/ext/standard/tests/array/array_diff_assoc_variation3.phpt +++ b/ext/standard/tests/array/array_diff_assoc_variation3.phpt @@ -10,10 +10,6 @@ echo "\n*** Testing array_diff_assoc() : usage variations ***\n"; $array = array(1, 2, 3); -//get an unset variable -$unset_var = 10; -unset ($unset_var); - // get a class class classA { @@ -22,11 +18,6 @@ class classA } } -// heredoc string -$heredoc = << array( - NULL, null), // boolean data /*4*/ 'bool' => array( true, - false, - TRUE, - FALSE), + false), // empty data /*5*/ 'empty' => array( - "", ''), // string data /*6*/ 'string' => array( - "string", - 'string', - $heredoc), - - // binary data -/*7*/ -'binary' => array( - b"binary", - (binary)"binary"), + 'string'), // object data /*8*/ 'object' => array( new classA()), - - // undefined data -/*9*/ -'undefined' => array( - @$undefined_var), - - // unset data -/*10*/ -'unset' => array( - @$unset_var), ); // loop through each element of $inputs to check the behavior of array_diff_assoc @@ -135,65 +104,33 @@ array(5) { } -- Iteration 3 -- -array(2) { +array(1) { [0]=> NULL - [1]=> - NULL } -- Iteration 4 -- -array(3) { +array(1) { [1]=> bool(false) - [2]=> - bool(true) - [3]=> - bool(false) } -- Iteration 5 -- -array(2) { +array(1) { [0]=> string(0) "" - [1]=> - string(0) "" } -- Iteration 6 -- -array(3) { +array(1) { [0]=> string(6) "string" - [1]=> - string(6) "string" - [2]=> - string(11) "hello world" } -- Iteration 7 -- -array(2) { - [0]=> - string(6) "binary" - [1]=> - string(6) "binary" -} - --- Iteration 8 -- array(1) { [0]=> object(classA)#%d (0) { } } - --- Iteration 9 -- -array(1) { - [0]=> - NULL -} - --- Iteration 10 -- -array(1) { - [0]=> - NULL -} Done diff --git a/ext/standard/tests/array/array_diff_assoc_variation4.phpt b/ext/standard/tests/array/array_diff_assoc_variation4.phpt index 65b76dd9ebf90..794a367368eec 100644 --- a/ext/standard/tests/array/array_diff_assoc_variation4.phpt +++ b/ext/standard/tests/array/array_diff_assoc_variation4.phpt @@ -11,15 +11,6 @@ echo "\n*** Testing array_diff_assoc() : usage variations ***\n"; $array = array(1, 2, 3); -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -// heredoc string -$heredoc = << 'positive', -2345 => 'negative'), - // null data -/*3*/ -'null' => array( - NULL => 'null 1', - null => 'null 2'), - - // boolean data -/*4*/ -'bool' => array( - true => 'boolt', - false => 'boolf', - TRUE => 'boolT', - FALSE => 'boolF'), - // empty data /*5*/ 'empty' => array( - "" => 'emptyd', - '' => 'emptys'), + '' => 'empty'), // string data /*6*/ 'string' => array( - "string" => 'stringd', - 'string' => 'strings', - $heredoc => 'stringh'), - - // binary data -/*7*/ -'binary' => array( - b"binary1" => 'binary 1', - (binary)"binary2" => 'binary 2'), - - // undefined data -/*8*/ -'undefined' => array( - @$undefined_var => 'undefined'), - - // unset data -/*9*/ -'unset' => array( - @$unset_var => 'unset'), + 'string' => 'strings'), ); @@ -104,48 +62,12 @@ array(4) { -- Iteration 2 -- array(1) { [""]=> - string(6) "null 2" + string(5) "empty" } -- Iteration 3 -- -array(2) { - [1]=> - string(5) "boolT" - [0]=> - string(5) "boolF" -} - --- Iteration 4 -- array(1) { - [""]=> - string(6) "emptys" -} - --- Iteration 5 -- -array(2) { ["string"]=> string(7) "strings" - ["hello world"]=> - string(7) "stringh" -} - --- Iteration 6 -- -array(2) { - ["binary1"]=> - string(8) "binary 1" - ["binary2"]=> - string(8) "binary 2" -} - --- Iteration 7 -- -array(1) { - [""]=> - string(9) "undefined" -} - --- Iteration 8 -- -array(1) { - [""]=> - string(5) "unset" } Done diff --git a/ext/standard/tests/array/array_diff_variation1.phpt b/ext/standard/tests/array/array_diff_variation1.phpt deleted file mode 100644 index 1031b6f947e0c..0000000000000 --- a/ext/standard/tests/array/array_diff_variation1.phpt +++ /dev/null @@ -1,154 +0,0 @@ ---TEST-- -Test array_diff() function : usage variations - unexpected values for 'array1' argument ---FILE-- -getMessage(), "\n"; - } - $iterator++; -}; - -fclose($fp); -echo "Done"; -?> ---EXPECT-- -*** Testing array_diff() : usage variations *** - --- Iteration 1 --array_diff(): Argument #1 ($array) must be of type array, int given - --- Iteration 2 --array_diff(): Argument #1 ($array) must be of type array, int given - --- Iteration 3 --array_diff(): Argument #1 ($array) must be of type array, int given - --- Iteration 4 --array_diff(): Argument #1 ($array) must be of type array, int given - --- Iteration 5 --array_diff(): Argument #1 ($array) must be of type array, float given - --- Iteration 6 --array_diff(): Argument #1 ($array) must be of type array, float given - --- Iteration 7 --array_diff(): Argument #1 ($array) must be of type array, float given - --- Iteration 8 --array_diff(): Argument #1 ($array) must be of type array, float given - --- Iteration 9 --array_diff(): Argument #1 ($array) must be of type array, float given - --- Iteration 10 --array_diff(): Argument #1 ($array) must be of type array, null given - --- Iteration 11 --array_diff(): Argument #1 ($array) must be of type array, null given - --- Iteration 12 --array_diff(): Argument #1 ($array) must be of type array, true given - --- Iteration 13 --array_diff(): Argument #1 ($array) must be of type array, false given - --- Iteration 14 --array_diff(): Argument #1 ($array) must be of type array, true given - --- Iteration 15 --array_diff(): Argument #1 ($array) must be of type array, false given - --- Iteration 16 --array_diff(): Argument #1 ($array) must be of type array, string given - --- Iteration 17 --array_diff(): Argument #1 ($array) must be of type array, string given - --- Iteration 18 --array_diff(): Argument #1 ($array) must be of type array, string given - --- Iteration 19 --array_diff(): Argument #1 ($array) must be of type array, string given - --- Iteration 20 --array_diff(): Argument #1 ($array) must be of type array, string given - --- Iteration 21 --array_diff(): Argument #1 ($array) must be of type array, string given - --- Iteration 22 --array_diff(): Argument #1 ($array) must be of type array, string given - --- Iteration 23 --array_diff(): Argument #1 ($array) must be of type array, classA given - --- Iteration 24 --array_diff(): Argument #1 ($array) must be of type array, null given - --- Iteration 25 --array_diff(): Argument #1 ($array) must be of type array, null given - --- Iteration 26 --array_diff(): Argument #1 ($array) must be of type array, resource given -Done diff --git a/ext/standard/tests/array/array_diff_variation2.phpt b/ext/standard/tests/array/array_diff_variation2.phpt deleted file mode 100644 index 2b03f22513695..0000000000000 --- a/ext/standard/tests/array/array_diff_variation2.phpt +++ /dev/null @@ -1,153 +0,0 @@ ---TEST-- -Test array_diff() function : usage variations - unexpected values for 'array2' argument ---FILE-- -getMessage(), "\n"; - } - $iterator++; -}; -fclose($fp); -echo "Done"; -?> ---EXPECT-- -*** Testing array_diff() : usage variations *** - --- Iteration 1 --array_diff(): Argument #2 must be of type array, int given - --- Iteration 2 --array_diff(): Argument #2 must be of type array, int given - --- Iteration 3 --array_diff(): Argument #2 must be of type array, int given - --- Iteration 4 --array_diff(): Argument #2 must be of type array, int given - --- Iteration 5 --array_diff(): Argument #2 must be of type array, float given - --- Iteration 6 --array_diff(): Argument #2 must be of type array, float given - --- Iteration 7 --array_diff(): Argument #2 must be of type array, float given - --- Iteration 8 --array_diff(): Argument #2 must be of type array, float given - --- Iteration 9 --array_diff(): Argument #2 must be of type array, float given - --- Iteration 10 --array_diff(): Argument #2 must be of type array, null given - --- Iteration 11 --array_diff(): Argument #2 must be of type array, null given - --- Iteration 12 --array_diff(): Argument #2 must be of type array, true given - --- Iteration 13 --array_diff(): Argument #2 must be of type array, false given - --- Iteration 14 --array_diff(): Argument #2 must be of type array, true given - --- Iteration 15 --array_diff(): Argument #2 must be of type array, false given - --- Iteration 16 --array_diff(): Argument #2 must be of type array, string given - --- Iteration 17 --array_diff(): Argument #2 must be of type array, string given - --- Iteration 18 --array_diff(): Argument #2 must be of type array, string given - --- Iteration 19 --array_diff(): Argument #2 must be of type array, string given - --- Iteration 20 --array_diff(): Argument #2 must be of type array, string given - --- Iteration 21 --array_diff(): Argument #2 must be of type array, string given - --- Iteration 22 --array_diff(): Argument #2 must be of type array, string given - --- Iteration 23 --array_diff(): Argument #2 must be of type array, classA given - --- Iteration 24 --array_diff(): Argument #2 must be of type array, null given - --- Iteration 25 --array_diff(): Argument #2 must be of type array, null given - --- Iteration 26 --array_diff(): Argument #2 must be of type array, resource given -Done diff --git a/ext/standard/tests/array/array_diff_variation3.phpt b/ext/standard/tests/array/array_diff_variation3.phpt index 37b295b0bd69c..649dcb5c92abb 100644 --- a/ext/standard/tests/array/array_diff_variation3.phpt +++ b/ext/standard/tests/array/array_diff_variation3.phpt @@ -12,15 +12,6 @@ echo "*** Testing array_diff() : usage variations ***\n"; // Initialise function arguments not being substituted (if any) $array = array(1, 2); -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -//get heredoc -$heredoc = << array( // null data - NULL, null), /*5*/ "boolean" => array( // boolean data true, - false, - TRUE, - FALSE), + false), /*6*/ -"empty" => array( - // empty data - "", - ''), +"empty" => array(''), /*7*/ -"string" => array( - // string data - "string", - 'string', - $heredoc), - -/*8*/ -"binary" => array( - // binary data - b"binary", - (binary)"binary"), - -/*9*/ -"undefined" => array( - // undefined data - @$undefined_var), - -/*10*/ -"unset" => array( - // unset data - @$unset_var) +"string" => array('string'), ); // loop through each element of the array for arr1 $iterator = 1; foreach($values as $value) { - echo "\n Iteration: $iterator \n"; + echo "Iteration: $iterator\n"; var_dump( array_diff($value, $array) ); $iterator++; }; @@ -99,12 +64,10 @@ echo "Done"; ?> --EXPECT-- *** Testing array_diff() : usage variations *** - - Iteration: 1 +Iteration: 1 array(0) { } - - Iteration: 2 +Iteration: 2 array(3) { [0]=> int(0) @@ -113,8 +76,7 @@ array(3) { [3]=> int(-2345) } - - Iteration: 3 +Iteration: 3 array(5) { [0]=> float(10.5) @@ -127,58 +89,24 @@ array(5) { [4]=> float(0.5) } - - Iteration: 4 -array(2) { +Iteration: 4 +array(1) { [0]=> NULL - [1]=> - NULL } - - Iteration: 5 -array(2) { +Iteration: 5 +array(1) { [1]=> bool(false) - [3]=> - bool(false) -} - - Iteration: 6 -array(2) { - [0]=> - string(0) "" - [1]=> - string(0) "" -} - - Iteration: 7 -array(3) { - [0]=> - string(6) "string" - [1]=> - string(6) "string" - [2]=> - string(17) "This is a heredoc" } - - Iteration: 8 -array(2) { - [0]=> - string(6) "binary" - [1]=> - string(6) "binary" -} - - Iteration: 9 +Iteration: 6 array(1) { [0]=> - NULL + string(0) "" } - - Iteration: 10 +Iteration: 7 array(1) { [0]=> - NULL + string(6) "string" } Done diff --git a/ext/standard/tests/array/array_diff_variation4.phpt b/ext/standard/tests/array/array_diff_variation4.phpt index 090f162bc7d9f..301280bcea510 100644 --- a/ext/standard/tests/array/array_diff_variation4.phpt +++ b/ext/standard/tests/array/array_diff_variation4.phpt @@ -12,15 +12,6 @@ echo "*** Testing array_diff() : usage variations ***\n"; // Initialise function arguments not being substituted (if any) $array = array(1, 2); -//get an unset variable -$unset_var = 10; -unset ($unset_var); - -//get heredoc -$heredoc = << array( // null data - NULL, null), /*5*/ "boolean" => array( // boolean data true, - false, - TRUE, - FALSE), + false), /*6*/ "empty" => array( // empty data - "", ''), /*7*/ "string" => array( // string data - "string", - 'string', - $heredoc), - -/*8*/ -"binary" => array( - // binary data - b"binary", - (binary)"binary"), - -/*9*/ -"undefined" => array( - // undefined data - @$undefined_var), - -/*10*/ -"unset" => array( - // unset data - @$unset_var) + 'string'), ); // loop through each element of the array for $arr2 @@ -151,28 +120,4 @@ array(2) { [1]=> int(2) } - - Iteration: 8 -array(2) { - [0]=> - int(1) - [1]=> - int(2) -} - - Iteration: 9 -array(2) { - [0]=> - int(1) - [1]=> - int(2) -} - - Iteration: 10 -array(2) { - [0]=> - int(1) - [1]=> - int(2) -} Done diff --git a/ext/standard/tests/array/array_filter_variation9.phpt b/ext/standard/tests/array/array_filter_variation9.phpt index ff0dc7711718b..2e6efc0eda5d9 100644 --- a/ext/standard/tests/array/array_filter_variation9.phpt +++ b/ext/standard/tests/array/array_filter_variation9.phpt @@ -8,7 +8,7 @@ Test array_filter() function : usage variations - built-in functions as 'callbac echo "*** Testing array_filter() : usage variations - built-in functions as 'callback' argument ***\n"; -$input = array(0, 1, -1, 10, 100, 1000); +$input = array(0, 1, 10, 100); // using built-in function 'is_int' as 'callback' var_dump( array_filter($input, 'is_int') ); @@ -34,33 +34,25 @@ echo "Done" ?> --EXPECT-- *** Testing array_filter() : usage variations - built-in functions as 'callback' argument *** -array(6) { +array(4) { [0]=> int(0) [1]=> int(1) [2]=> - int(-1) - [3]=> int(10) - [4]=> + [3]=> int(100) - [5]=> - int(1000) } -array(6) { +array(4) { [0]=> int(0) [1]=> int(1) [2]=> - int(-1) - [3]=> int(10) - [4]=> + [3]=> int(100) - [5]=> - int(1000) } array_filter(): Argument #2 ($callback) must be a valid callback or null, function "echo" not found or invalid function name array_filter(): Argument #2 ($callback) must be a valid callback or null, function "isset" not found or invalid function name diff --git a/ext/standard/tests/array/array_key_exists.phpt b/ext/standard/tests/array/array_key_exists.phpt index 8cc2f9c5207c2..c0db558f25823 100644 --- a/ext/standard/tests/array/array_key_exists.phpt +++ b/ext/standard/tests/array/array_key_exists.phpt @@ -82,7 +82,7 @@ try { echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- *** Testing basic functionalities *** -- Iteration 1 -- bool(true) @@ -104,7 +104,11 @@ bool(true) ** Variation loop 1 ** -- Iteration 1 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -112,7 +116,11 @@ bool(false) bool(true) -- Iteration 2 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -120,7 +128,11 @@ bool(false) bool(true) -- Iteration 3 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -128,7 +140,11 @@ bool(false) bool(true) -- Iteration 4 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -136,7 +152,11 @@ bool(false) bool(true) -- Iteration 5 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -144,7 +164,11 @@ bool(false) bool(false) -- Iteration 6 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -152,7 +176,11 @@ bool(false) bool(false) -- Iteration 7 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -162,7 +190,11 @@ bool(true) ** Variation loop 2 ** -- Iteration 1 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -170,7 +202,11 @@ bool(false) bool(false) -- Iteration 2 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -178,7 +214,11 @@ bool(false) bool(false) -- Iteration 3 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) @@ -186,7 +226,11 @@ bool(false) bool(true) -- Iteration 4 -- bool(true) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(true) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(true) bool(false) bool(true) @@ -194,7 +238,11 @@ bool(false) bool(true) -- Iteration 5 -- bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) bool(false) bool(false) diff --git a/ext/standard/tests/array/array_key_exists_variation1.phpt b/ext/standard/tests/array/array_key_exists_variation1.phpt index e3133cfc8eb1c..d12fbc839b795 100644 --- a/ext/standard/tests/array/array_key_exists_variation1.phpt +++ b/ext/standard/tests/array/array_key_exists_variation1.phpt @@ -105,9 +105,13 @@ bool(false) bool(false) -- Iteration 5 -- + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) -- Iteration 6 -- + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) -- Iteration 7 -- @@ -144,9 +148,13 @@ bool(true) Cannot access offset of type classA on array -- Iteration 18 -- + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) -- Iteration 19 -- + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(false) -- Iteration 20 -- diff --git a/ext/standard/tests/array/array_key_exists_variation6.phpt b/ext/standard/tests/array/array_key_exists_variation6.phpt index fe16478833c5f..8c98a6971c029 100644 --- a/ext/standard/tests/array/array_key_exists_variation6.phpt +++ b/ext/standard/tests/array/array_key_exists_variation6.phpt @@ -36,54 +36,110 @@ foreach($array as $name => $input) { echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing array_key_exists() : usage variations *** -- Key in $search array is : null -- -Iteration 1: bool(true) -Iteration 2: bool(true) + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d +Iteration 1: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 2: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) Iteration 3: bool(true) Iteration 4: bool(true) -Iteration 5: bool(true) -Iteration 6: bool(true) +Iteration 5: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 6: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) -- Key in $search array is : NULL -- -Iteration 1: bool(true) -Iteration 2: bool(true) + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d +Iteration 1: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 2: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) Iteration 3: bool(true) Iteration 4: bool(true) -Iteration 5: bool(true) -Iteration 6: bool(true) +Iteration 5: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 6: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) -- Key in $search array is : empty single quoted string -- -Iteration 1: bool(true) -Iteration 2: bool(true) +Iteration 1: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 2: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) Iteration 3: bool(true) Iteration 4: bool(true) -Iteration 5: bool(true) -Iteration 6: bool(true) +Iteration 5: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 6: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) -- Key in $search array is : empty double quoted string -- -Iteration 1: bool(true) -Iteration 2: bool(true) +Iteration 1: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 2: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) Iteration 3: bool(true) Iteration 4: bool(true) -Iteration 5: bool(true) -Iteration 6: bool(true) +Iteration 5: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 6: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) -- Key in $search array is : undefined variable -- -Iteration 1: bool(true) -Iteration 2: bool(true) + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d +Iteration 1: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 2: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) Iteration 3: bool(true) Iteration 4: bool(true) -Iteration 5: bool(true) -Iteration 6: bool(true) +Iteration 5: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 6: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) -- Key in $search array is : unset variable -- -Iteration 1: bool(true) -Iteration 2: bool(true) + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d +Iteration 1: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 2: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) Iteration 3: bool(true) Iteration 4: bool(true) -Iteration 5: bool(true) -Iteration 6: bool(true) +Iteration 5: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +Iteration 6: +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) Done diff --git a/ext/standard/tests/array/bug20865.phpt b/ext/standard/tests/array/bug20865.phpt index 6dfad2bcec053..7401e98b1ab01 100644 --- a/ext/standard/tests/array/bug20865.phpt +++ b/ext/standard/tests/array/bug20865.phpt @@ -7,5 +7,8 @@ Bug #20865 (array_key_exists and NULL key) var_dump(array_key_exists(NULL, $ta)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d + +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d bool(true) diff --git a/ext/standard/tests/array/gh16649/array_splice_normal_destructor.phpt b/ext/standard/tests/array/gh16649/array_splice_normal_destructor.phpt new file mode 100644 index 0000000000000..59c0b316f54d5 --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_normal_destructor.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-16649: array_splice with normal destructor should work fine +--FILE-- + +--EXPECT-- +Destructor called +array(1) { + [0]=> + string(1) "1" +} diff --git a/ext/standard/tests/array/gh16649/array_splice_uaf_add_elements.phpt b/ext/standard/tests/array/gh16649/array_splice_uaf_add_elements.phpt new file mode 100644 index 0000000000000..f5e538122f415 --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_uaf_add_elements.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-16649: array_splice UAF when destructor adds elements to array +--FILE-- +getMessage() . "\n"; +} +?> +--EXPECT-- +Exception caught: Array was modified during array_splice operation diff --git a/ext/standard/tests/array/gh16649/array_splice_uaf_array_deallocated.phpt b/ext/standard/tests/array/gh16649/array_splice_uaf_array_deallocated.phpt new file mode 100644 index 0000000000000..1874ddad8934d --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_uaf_array_deallocated.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-16649: array_splice UAF when array is released entirely +--FILE-- +getMessage() . "\n"; +} +?> +--EXPECT-- +Exception caught: Array was modified during array_splice operation diff --git a/ext/standard/tests/array/gh16649/array_splice_uaf_complex_modification.phpt b/ext/standard/tests/array/gh16649/array_splice_uaf_complex_modification.phpt new file mode 100644 index 0000000000000..8ad4133300ec5 --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_uaf_complex_modification.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-16649: array_splice UAF with complex array modification +--FILE-- +getMessage() . "\n"; +} +?> +--EXPECT-- +Exception caught: Array was modified during array_splice operation diff --git a/ext/standard/tests/array/gh16649/array_splice_uaf_multiple_destructors.phpt b/ext/standard/tests/array/gh16649/array_splice_uaf_multiple_destructors.phpt new file mode 100644 index 0000000000000..9e2c6cf8fc715 --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_uaf_multiple_destructors.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-16649: array_splice UAF with multiple destructors +--FILE-- +id = $id; + } + + function __destruct() { + global $arr; + echo "Destructor {$this->id} called\n"; + if ($this->id == 2) { + $arr = null; + } + } +} + +$arr = ["start", new MultiDestructor(1), new MultiDestructor(2), "end"]; + +try { + array_splice($arr, 1, 2); + echo "ERROR: Should have thrown exception\n"; +} catch (Error $e) { + echo "Exception caught: " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +Destructor 1 called +Destructor 2 called +Exception caught: Array was modified during array_splice operation diff --git a/ext/standard/tests/array/gh16649/array_splice_uaf_original_case.phpt b/ext/standard/tests/array/gh16649/array_splice_uaf_original_case.phpt new file mode 100644 index 0000000000000..4a82d5893157d --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_uaf_original_case.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-16649: array_splice UAF with destructor modifying array (original case) +--FILE-- + "1", "3" => new C, "2" => "2"]; + +try { + array_splice($arr, 1, 2); + echo "ERROR: Should have thrown exception\n"; +} catch (Error $e) { + echo "Exception caught: " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +Exception caught: Array was modified during array_splice operation diff --git a/ext/standard/tests/array/gh16649/array_splice_uaf_packed_to_hash.phpt b/ext/standard/tests/array/gh16649/array_splice_uaf_packed_to_hash.phpt new file mode 100644 index 0000000000000..bd8f511b6253e --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_uaf_packed_to_hash.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-16649: array_splice UAF when array is converted from packed to hash +--FILE-- +getMessage() . "\n"; +} +?> +--EXPECT-- +Exception caught: Array was modified during array_splice operation diff --git a/ext/standard/tests/array/gh16649/array_splice_with_replacement.phpt b/ext/standard/tests/array/gh16649/array_splice_with_replacement.phpt new file mode 100644 index 0000000000000..8754a913a24e4 --- /dev/null +++ b/ext/standard/tests/array/gh16649/array_splice_with_replacement.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-16649: array_splice with replacement array when destructor modifies array +--FILE-- +getMessage() . "\n"; +} +?> +--EXPECT-- +Exception caught: Array was modified during array_splice operation diff --git a/ext/standard/tests/array/gh19300_1.phpt b/ext/standard/tests/array/gh19300_1.phpt new file mode 100644 index 0000000000000..18b639bf425b8 --- /dev/null +++ b/ext/standard/tests/array/gh19300_1.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-19300 (Nested array_multisort invocation with error breaks) - correct invocation variation +--FILE-- +data; + } +} + +$inputs = [ + new MyStringable('3'), + new MyStringable('1'), + new MyStringable('2'), +]; + +var_dump(array_multisort($inputs, SORT_STRING)); +var_dump($inputs); +?> +--EXPECT-- +bool(true) +array(3) { + [0]=> + object(MyStringable)#2 (1) { + ["data":"MyStringable":private]=> + string(1) "1" + } + [1]=> + object(MyStringable)#3 (1) { + ["data":"MyStringable":private]=> + string(1) "2" + } + [2]=> + object(MyStringable)#1 (1) { + ["data":"MyStringable":private]=> + string(1) "3" + } +} diff --git a/ext/standard/tests/array/gh19300_2.phpt b/ext/standard/tests/array/gh19300_2.phpt new file mode 100644 index 0000000000000..41ae7e82bb796 --- /dev/null +++ b/ext/standard/tests/array/gh19300_2.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-19300 (Nested array_multisort invocation with error breaks) - error variation +--FILE-- +getMessage(), "\n"; + } +} +set_error_handler('error_handle'); + +$inputs = [ + new stdClass, + new stdClass, + new stdClass, +]; + +var_dump(array_multisort($inputs, SORT_NUMERIC)); +var_dump($inputs); +?> +--EXPECT-- +array_multisort(): Argument #1 ($array) must be an array or a sort flag +array_multisort(): Argument #1 ($array) must be an array or a sort flag +array_multisort(): Argument #1 ($array) must be an array or a sort flag +array_multisort(): Argument #1 ($array) must be an array or a sort flag +bool(true) +array(3) { + [0]=> + object(stdClass)#1 (0) { + } + [1]=> + object(stdClass)#2 (0) { + } + [2]=> + object(stdClass)#3 (0) { + } +} diff --git a/ext/standard/tests/array/rcn_in_place.phpt b/ext/standard/tests/array/rcn_in_place.phpt new file mode 100644 index 0000000000000..e6a7b5b6d695f --- /dev/null +++ b/ext/standard/tests/array/rcn_in_place.phpt @@ -0,0 +1,57 @@ +--TEST-- +RCN check for in-place array modifications +--FILE-- + 0)); +var_dump(array_intersect(range(0, 1), [])); +var_dump(array_uintersect(range(0, 1), [], fn () => 0)); +var_dump(array_intersect_uassoc(range(0, 1), [], fn () => 0)); +var_dump(array_uintersect_uassoc(range(0, 1), [], fn () => 0, fn () => 0)); +?> +--EXPECT-- +array(2) { + [0]=> + int(0) + [1]=> + int(1) +} +array(2) { + [0]=> + int(0) + [1]=> + int(1) +} +array(2) { + [0]=> + int(0) + [1]=> + int(1) +} +array(2) { + [0]=> + int(0) + [1]=> + int(1) +} +array(2) { + [0]=> + int(0) + [1]=> + int(1) +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} diff --git a/ext/standard/tests/assert/assert.phpt b/ext/standard/tests/assert/assert.phpt index 4649e9a59be94..a275b9949cbe6 100644 --- a/ext/standard/tests/assert/assert.phpt +++ b/ext/standard/tests/assert/assert.phpt @@ -41,25 +41,25 @@ Deprecated: PHP Startup: assert.active INI setting is deprecated in Unknown on l Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_ACTIVE is deprecated in %s on line %d +Deprecated: Constant ASSERT_ACTIVE is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_WARNING is deprecated in %s on line %d +Deprecated: Constant ASSERT_WARNING is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d assertion failed 21,"assert($a != 0)" -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d class assertion failed 24,"assert($a != 0)" -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d class assertion failed 28,"assert($a != 0)" diff --git a/ext/standard/tests/assert/assert03.phpt b/ext/standard/tests/assert/assert03.phpt index 2a62665893a88..968af83065036 100644 --- a/ext/standard/tests/assert/assert03.phpt +++ b/ext/standard/tests/assert/assert03.phpt @@ -36,15 +36,15 @@ Deprecated: PHP Startup: assert.warning INI setting is deprecated in Unknown on Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_ACTIVE is deprecated in %s on line %d +Deprecated: Constant ASSERT_ACTIVE is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_WARNING is deprecated in %s on line %d +Deprecated: Constant ASSERT_WARNING is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d assertion failed - a - 18,"assert($a != 0)" diff --git a/ext/standard/tests/assert/assert04.phpt b/ext/standard/tests/assert/assert04.phpt index 9935d4c6a123c..744633c197be2 100644 --- a/ext/standard/tests/assert/assert04.phpt +++ b/ext/standard/tests/assert/assert04.phpt @@ -29,17 +29,17 @@ echo "not reached\n"; --EXPECTF-- Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_ACTIVE is deprecated in %s on line %d +Deprecated: Constant ASSERT_ACTIVE is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_ACTIVE is deprecated in %s on line %d +Deprecated: Constant ASSERT_ACTIVE is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d Warning: assert(): assert(0) failed in %s on line %d -Deprecated: Constant ASSERT_BAIL is deprecated in %s on line %d +Deprecated: Constant ASSERT_BAIL is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d diff --git a/ext/standard/tests/assert/assert_basic2.phpt b/ext/standard/tests/assert/assert_basic2.phpt index fdd1c53b93dde..6bca82a91f536 100644 --- a/ext/standard/tests/assert/assert_basic2.phpt +++ b/ext/standard/tests/assert/assert_basic2.phpt @@ -30,7 +30,7 @@ Deprecated: PHP Startup: assert.callback INI setting is deprecated in Unknown on Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(2) "f1" @@ -38,12 +38,12 @@ f1 called Warning: assert(): assert(0) failed in %s on line %d -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(2) "f1" -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(2) "f2" diff --git a/ext/standard/tests/assert/assert_basic3.phpt b/ext/standard/tests/assert/assert_basic3.phpt index 0849f16e6f208..4e281ef504245 100644 --- a/ext/standard/tests/assert/assert_basic3.phpt +++ b/ext/standard/tests/assert/assert_basic3.phpt @@ -23,7 +23,7 @@ Deprecated: PHP Startup: assert.callback INI setting is deprecated in Unknown on Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_BAIL is deprecated in %s on line %d +Deprecated: Constant ASSERT_BAIL is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d int(0) diff --git a/ext/standard/tests/assert/assert_basic4.phpt b/ext/standard/tests/assert/assert_basic4.phpt index 76ade8d00f403..cc9ec64328866 100644 --- a/ext/standard/tests/assert/assert_basic4.phpt +++ b/ext/standard/tests/assert/assert_basic4.phpt @@ -28,22 +28,22 @@ Deprecated: PHP Startup: assert.warning INI setting is deprecated in Unknown on Deprecated: PHP Startup: assert.callback INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_ACTIVE is deprecated in %s on line %d +Deprecated: Constant ASSERT_ACTIVE is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d Initial values: assert_options(ASSERT_ACTIVE) => [0] -Deprecated: Constant ASSERT_WARNING is deprecated in %s on line %d +Deprecated: Constant ASSERT_WARNING is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d Initial values: assert_options(ASSERT_WARNING) => [0] -Deprecated: Constant ASSERT_BAIL is deprecated in %s on line %d +Deprecated: Constant ASSERT_BAIL is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d Initial values: assert_options(ASSERT_BAIL) => [0] -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d Initial values: assert_options(ASSERT_CALLBACK) => [f1] diff --git a/ext/standard/tests/assert/assert_basic5.phpt b/ext/standard/tests/assert/assert_basic5.phpt index 6ba70d94cdf36..66858eed5cb81 100644 --- a/ext/standard/tests/assert/assert_basic5.phpt +++ b/ext/standard/tests/assert/assert_basic5.phpt @@ -28,7 +28,7 @@ Deprecated: PHP Startup: assert.callback INI setting is deprecated in Unknown on Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_WARNING is deprecated in %s on line %d +Deprecated: Constant ASSERT_WARNING is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d int(0) @@ -38,7 +38,7 @@ Warning: assert(): assert(0 != 0) failed in %s on line %d bool(false) bool(true) -Deprecated: Constant ASSERT_WARNING is deprecated in %s on line %d +Deprecated: Constant ASSERT_WARNING is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d int(1) diff --git a/ext/standard/tests/assert/assert_basic6.phpt b/ext/standard/tests/assert/assert_basic6.phpt index 4e95fdb01dc4c..b531425912c21 100644 --- a/ext/standard/tests/assert/assert_basic6.phpt +++ b/ext/standard/tests/assert/assert_basic6.phpt @@ -32,11 +32,11 @@ try { ?> --EXPECTF-- -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(2) "f1" @@ -44,11 +44,11 @@ foo assert(false) -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d NULL diff --git a/ext/standard/tests/assert/assert_closures.phpt b/ext/standard/tests/assert/assert_closures.phpt index aa7246ee21bee..ecce049860236 100644 --- a/ext/standard/tests/assert/assert_closures.phpt +++ b/ext/standard/tests/assert/assert_closures.phpt @@ -13,7 +13,7 @@ assert(0); --EXPECTF-- Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d Hello World! diff --git a/ext/standard/tests/assert/assert_closures_multiple.phpt b/ext/standard/tests/assert/assert_closures_multiple.phpt index 0786740155571..8f0cb9551ab93 100644 --- a/ext/standard/tests/assert/assert_closures_multiple.phpt +++ b/ext/standard/tests/assert/assert_closures_multiple.phpt @@ -32,7 +32,7 @@ try { ?> DONE --EXPECTF-- -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d DONE diff --git a/ext/standard/tests/assert/assert_error2.phpt b/ext/standard/tests/assert/assert_error2.phpt index eaa62523845d4..6cfa5a6ce4447 100644 --- a/ext/standard/tests/assert/assert_error2.phpt +++ b/ext/standard/tests/assert/assert_error2.phpt @@ -25,7 +25,7 @@ Deprecated: PHP Startup: assert.callback INI setting is deprecated in Unknown on Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_BAIL is deprecated in %s on line %d +Deprecated: Constant ASSERT_BAIL is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d int(0) diff --git a/ext/standard/tests/assert/assert_variation.phpt b/ext/standard/tests/assert/assert_variation.phpt index 494f6cd579384..6824f7246d5b6 100644 --- a/ext/standard/tests/assert/assert_variation.phpt +++ b/ext/standard/tests/assert/assert_variation.phpt @@ -85,7 +85,7 @@ Deprecated: PHP Startup: assert.callback INI setting is deprecated in Unknown on Deprecated: PHP Startup: assert.exception INI setting is deprecated in Unknown on line 0 -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d Initial values: assert_options(ASSERT_CALLBACK) => [f1] @@ -98,7 +98,7 @@ Change callback function using ini.set and test return value Deprecated: ini_set(): assert.callback INI setting is deprecated in %s on line %d string(2) "f1" -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d assert_options(ASSERT_CALLBACK) => [f2] @@ -108,12 +108,12 @@ bool(false) Change callback function using assert_options and test return value -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(2) "f2" -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d assert_options(ASSERT_CALLBACK) => [f3] @@ -123,12 +123,12 @@ bool(false) Reset the name of the callback routine to a class method -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(2) "f3" -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d assert_options(ASSERT_CALLBACK) => [c1] @@ -137,12 +137,12 @@ Invalid callback c1, function "c1" not found or invalid function name Reset callback options to use a class method -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(2) "c1" -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d array(2) { @@ -158,7 +158,7 @@ bool(false) Reset callback options to use an object method -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d array(2) { @@ -168,7 +168,7 @@ array(2) { string(6) "assert" } -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d array(2) { @@ -185,11 +185,11 @@ bool(false) Set callback to something silly -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d float(3.141) diff --git a/ext/standard/tests/assert/bug80290.phpt b/ext/standard/tests/assert/bug80290.phpt index 8b737f33043f9..112dbde1a4e47 100644 --- a/ext/standard/tests/assert/bug80290.phpt +++ b/ext/standard/tests/assert/bug80290.phpt @@ -12,7 +12,7 @@ assert(false, 'Dynamic message: ' . $x); ?> --EXPECTF-- -Deprecated: Constant ASSERT_CALLBACK is deprecated in %s on line %d +Deprecated: Constant ASSERT_CALLBACK is deprecated since 8.3, as assert_options() is deprecated in %s on line %d Deprecated: Function assert_options() is deprecated since 8.3 in %s on line %d string(18) "Dynamic message: x" diff --git a/ext/standard/tests/class_object/get_object_vars_variation_005.phpt b/ext/standard/tests/class_object/get_object_vars_variation_005.phpt index 1ad1bb3933293..2fed6468c5304 100644 --- a/ext/standard/tests/class_object/get_object_vars_variation_005.phpt +++ b/ext/standard/tests/class_object/get_object_vars_variation_005.phpt @@ -25,6 +25,7 @@ var_dump(get_object_vars($obj)); ?> --EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d array(3) { ["%0A%0b"]=> int(42) @@ -33,6 +34,8 @@ array(3) { [12]=> int(6) } + +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d array(4) { ["prop"]=> NULL diff --git a/ext/standard/tests/dir/bug73877.phpt b/ext/standard/tests/dir/bug73877.phpt index ceb272ea6527d..e538bed0d8908 100644 --- a/ext/standard/tests/dir/bug73877.phpt +++ b/ext/standard/tests/dir/bug73877.phpt @@ -18,7 +18,7 @@ $junk0 = $base . DIRECTORY_SEPARATOR . "Серёжка2"; mkdir($base); mkdir($dir0); mkdir($dir1); -`mklink /J $junk0 $dir0`; +shell_exec("mklink /J $junk0 $dir0"); var_dump( readlink($dir0), diff --git a/ext/standard/tests/dir/closedir_basic-win32-mb.phpt b/ext/standard/tests/dir/closedir_basic-win32-mb.phpt index 05cb1889c9485..3754963a85009 100644 --- a/ext/standard/tests/dir/closedir_basic-win32-mb.phpt +++ b/ext/standard/tests/dir/closedir_basic-win32-mb.phpt @@ -44,6 +44,8 @@ rmdir($dir_path); *** Testing closedir() : basic functionality *** -- Call closedir() with no arguments: -- + +Deprecated: closedir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d NULL -- Check Directory Handle: -- resource(%d) of type (Unknown) diff --git a/ext/standard/tests/dir/closedir_basic.phpt b/ext/standard/tests/dir/closedir_basic.phpt index aa4be6fbaf279..82065f01419ab 100644 --- a/ext/standard/tests/dir/closedir_basic.phpt +++ b/ext/standard/tests/dir/closedir_basic.phpt @@ -38,6 +38,8 @@ rmdir($dir_path); *** Testing closedir() : basic functionality *** -- Call closedir() with no arguments: -- + +Deprecated: closedir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d NULL -- Check Directory Handle: -- resource(%d) of type (Unknown) diff --git a/ext/standard/tests/dir/closedir_without_arg.phpt b/ext/standard/tests/dir/closedir_without_arg.phpt index 27884c1a2b645..f248764ed2a69 100644 --- a/ext/standard/tests/dir/closedir_without_arg.phpt +++ b/ext/standard/tests/dir/closedir_without_arg.phpt @@ -8,5 +8,6 @@ try { echo $e->getMessage(), "\n"; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: closedir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d No resource supplied diff --git a/ext/standard/tests/dir/readdir_basic-win32-mb.phpt b/ext/standard/tests/dir/readdir_basic-win32-mb.phpt index d7e0804d57b35..dd97566db0796 100644 --- a/ext/standard/tests/dir/readdir_basic-win32-mb.phpt +++ b/ext/standard/tests/dir/readdir_basic-win32-mb.phpt @@ -65,6 +65,18 @@ string(9) "file3.tmp" -- Call readdir() without $path argument -- resource(%d) of type (stream) + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d string(1) "." string(2) ".." string(9) "file1.tmp" diff --git a/ext/standard/tests/dir/readdir_basic.phpt b/ext/standard/tests/dir/readdir_basic.phpt index 01ddd694adcbf..fbabfc6e9b2b3 100644 --- a/ext/standard/tests/dir/readdir_basic.phpt +++ b/ext/standard/tests/dir/readdir_basic.phpt @@ -59,6 +59,18 @@ string(9) "file3.tmp" -- Call readdir() without $path argument -- resource(%d) of type (stream) + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d string(1) "." string(2) ".." string(9) "file1.tmp" diff --git a/ext/standard/tests/dir/readdir_variation6-win32-mb.phpt b/ext/standard/tests/dir/readdir_variation6-win32-mb.phpt index 91062e76bd4f9..c2bfe7d1a2b4a 100644 --- a/ext/standard/tests/dir/readdir_variation6-win32-mb.phpt +++ b/ext/standard/tests/dir/readdir_variation6-win32-mb.phpt @@ -61,7 +61,7 @@ closedir(); $dir_path = __DIR__ . "/私はガラスを食べられますreaddir_variation6"; rmdir($dir_path); ?> ---EXPECT-- +--EXPECTF-- *** Testing readdir() : usage variations *** -- Reading Directory Contents with Previous Handle -- @@ -72,8 +72,22 @@ string(59) "私はガラスを食べられますreaddir_variation62.tmp" string(59) "私はガラスを食べられますreaddir_variation63.tmp" -- Reading Directory Contents with Current Handle (no arguments supplied) -- + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d string(1) "." string(2) ".." string(59) "私はガラスを食べられますreaddir_variation61.tmp" string(59) "私はガラスを食べられますreaddir_variation62.tmp" string(59) "私はガラスを食べられますreaddir_variation63.tmp" + +Deprecated: closedir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d diff --git a/ext/standard/tests/dir/readdir_variation6.phpt b/ext/standard/tests/dir/readdir_variation6.phpt index b017789f31ac8..9865a1d4fc608 100644 --- a/ext/standard/tests/dir/readdir_variation6.phpt +++ b/ext/standard/tests/dir/readdir_variation6.phpt @@ -55,7 +55,7 @@ closedir(); $dir_path = __DIR__ . "/readdir_variation6"; rmdir($dir_path); ?> ---EXPECT-- +--EXPECTF-- *** Testing readdir() : usage variations *** -- Reading Directory Contents with Previous Handle -- @@ -66,8 +66,22 @@ string(23) "readdir_variation62.tmp" string(23) "readdir_variation63.tmp" -- Reading Directory Contents with Current Handle (no arguments supplied) -- + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d string(1) "." string(2) ".." string(23) "readdir_variation61.tmp" string(23) "readdir_variation62.tmp" string(23) "readdir_variation63.tmp" + +Deprecated: closedir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d diff --git a/ext/standard/tests/dir/rewinddir_basic-win32-mb.phpt b/ext/standard/tests/dir/rewinddir_basic-win32-mb.phpt index a20501d3caded..2ec56418c85bf 100644 --- a/ext/standard/tests/dir/rewinddir_basic-win32-mb.phpt +++ b/ext/standard/tests/dir/rewinddir_basic-win32-mb.phpt @@ -82,6 +82,14 @@ NULL bool(true) -- Read and rewind second directory (no argument supplied) -- + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d array(3) { [0]=> string(1) "." @@ -90,5 +98,9 @@ array(3) { [2]=> string(45) "私はガラスを食べられますfile2.tmp" } + +Deprecated: rewinddir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d NULL + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d bool(true) diff --git a/ext/standard/tests/dir/rewinddir_basic.phpt b/ext/standard/tests/dir/rewinddir_basic.phpt index faee6b9bd64a4..106c00051d6e7 100644 --- a/ext/standard/tests/dir/rewinddir_basic.phpt +++ b/ext/standard/tests/dir/rewinddir_basic.phpt @@ -76,6 +76,14 @@ NULL bool(true) -- Read and rewind second directory (no argument supplied) -- + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d array(3) { [0]=> string(1) "." @@ -84,5 +92,9 @@ array(3) { [2]=> string(9) "file2.tmp" } + +Deprecated: rewinddir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d NULL + +Deprecated: readdir(): Passing null is deprecated, instead the last opened directory stream should be provided in %s on line %d bool(true) diff --git a/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt b/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt index 91416f2c71202..5af789ff424a5 100644 --- a/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt +++ b/ext/standard/tests/directory/DirectoryClass_readonly_handle_by_pass_via_ArrayObject.phpt @@ -28,7 +28,8 @@ try { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants in %s on line %d resource(3) of type (stream) Error: Internal directory stream has been altered Error: Typed property Directory::$handle must not be accessed before initialization diff --git a/ext/standard/tests/file/bug81145.phpt b/ext/standard/tests/file/bug81145.phpt index f3258ff6019e9..27026176193f3 100644 --- a/ext/standard/tests/file/bug81145.phpt +++ b/ext/standard/tests/file/bug81145.phpt @@ -9,8 +9,8 @@ if (PHP_OS_FAMILY !== "Windows") { $src = __DIR__ . "/bug81145_src.bin"; define('SIZE_4G', 0x100000000); exec("fallocate -l " . (SIZE_4G-0x100) . " " . escapeshellarg($src), $output, $status); - if ($status !== 0) die("skip fallocate() not supported"); @unlink(__DIR__ . "/bug81145_src.bin"); + if ($status !== 0) die("skip fallocate() not supported"); } ?> --CONFLICTS-- diff --git a/ext/standard/tests/file/chmod_variation2.phpt b/ext/standard/tests/file/chmod_variation2.phpt index e96af25ec469b..c2b6c2e810a3c 100644 --- a/ext/standard/tests/file/chmod_variation2.phpt +++ b/ext/standard/tests/file/chmod_variation2.phpt @@ -34,7 +34,7 @@ clearstatcache(); printf("%o\n", fileperms($filepath) & PERMISSIONS_MASK); echo "\nchmod() on a linked file\n"; -$linkname = "somelink"; +$linkname = "somelink2"; var_dump(symlink($filepath, $linkname)); var_dump(chmod($filepath, 0777)); var_dump(chmod($linkname, 0755)); diff --git a/ext/standard/tests/file/file_binary_text_deprecated.phpt b/ext/standard/tests/file/file_binary_text_deprecated.phpt index cbc57809c6175..b6967c5967103 100644 --- a/ext/standard/tests/file/file_binary_text_deprecated.phpt +++ b/ext/standard/tests/file/file_binary_text_deprecated.phpt @@ -8,8 +8,8 @@ var_dump(FILE_TEXT); ?> --EXPECTF-- -Deprecated: Constant FILE_BINARY is deprecated in %s on line %d +Deprecated: Constant FILE_BINARY is deprecated since 8.1, as the constant has no effect in %s on line %d int(0) -Deprecated: Constant FILE_TEXT is deprecated in %s on line %d +Deprecated: Constant FILE_TEXT is deprecated since 8.1, as the constant has no effect in %s on line %d int(0) diff --git a/ext/standard/tests/file/file_get_contents_with_custom_uri_parser.phpt b/ext/standard/tests/file/file_get_contents_with_custom_uri_parser.phpt new file mode 100644 index 0000000000000..b5070b7402382 --- /dev/null +++ b/ext/standard/tests/file/file_get_contents_with_custom_uri_parser.phpt @@ -0,0 +1,49 @@ +--TEST-- +Test file_get_contents() function when a custom URI parser is configured +--FILE-- + [ + "uri_parser_class" => "not-exists", + ], + ]); + var_dump(file_get_contents("http://example.com", context: $context)); +} catch (Error $e) { + echo $e->getMessage() . "\n"; +} + +$context = stream_context_create([ + "http" => [ + "uri_parser_class" => null, + ], +]); +var_dump(file_get_contents("http:///example.com", context: $context)); // invalid for parse_url only, valid for the other handlers + +$context = stream_context_create([ + "http" => [ + "uri_parser_class" => \Uri\Rfc3986\Uri::class, + ], +]); +var_dump(file_get_contents("http://éxamplé.com", context: $context)); // invalid for RFC 3986 only, valid for the other handlers + +$context = stream_context_create([ + "http" => [ + "uri_parser_class" => \Uri\WhatWg\Url::class, + ], +]); +var_dump(file_get_contents("http://exa%23mple.org", context: $context)); // invalid for WHATWG only, valid for the other handlers + +?> +--EXPECTF-- +file_get_contents(): Provided stream context has invalid value for the "uri_parser_class" option + +Warning: file_get_contents(http:///example.com): Failed to open stream: operation failed in %s on line %d +bool(false) + +Warning: file_get_contents(http://éxamplé.com): Failed to open stream: operation failed in %s on line %d +bool(false) + +Warning: file_get_contents(http://exa%23mple.org): Failed to open stream: operation failed in %s on line %d +bool(false) diff --git a/ext/standard/tests/file/file_variation5.phpt b/ext/standard/tests/file/file_variation5.phpt index d1c5e1498bebd..3db848cdbbfbd 100644 --- a/ext/standard/tests/file/file_variation5.phpt +++ b/ext/standard/tests/file/file_variation5.phpt @@ -27,7 +27,7 @@ echo "\nfile() on a path containing .. with invalid directories\n"; var_dump(file("./$test_dirname/bad_dir/../../$filename")); echo "\nfile() on a linked file\n"; -$linkname = "somelink"; +$linkname = "somelink5"; var_dump(symlink($filepath, $linkname)); var_dump(file($linkname)); var_dump(unlink($linkname)); diff --git a/ext/standard/tests/file/fread_socket_variation1.phpt b/ext/standard/tests/file/fread_socket_variation1.phpt index 09b3d65393abd..62d4b33ba486d 100644 --- a/ext/standard/tests/file/fread_socket_variation1.phpt +++ b/ext/standard/tests/file/fread_socket_variation1.phpt @@ -12,7 +12,7 @@ for ($i=0; $i<100; $i++) { } } -socket_set_timeout($server, 0, 1000); +stream_set_timeout($server, 0, 1000); var_dump(fread($server, 1)); diff --git a/ext/standard/tests/file/mkdir-002.phpt b/ext/standard/tests/file/mkdir-002.phpt index f4a42a7d61982..d48b19e645bad 100644 --- a/ext/standard/tests/file/mkdir-002.phpt +++ b/ext/standard/tests/file/mkdir-002.phpt @@ -11,13 +11,13 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { var_dump(mkdir("mkdir-002", 0777)); var_dump(mkdir("mkdir-002/subdir", 0777)); -var_dump(`ls -l mkdir-002`); +var_dump(shell_exec("ls -l mkdir-002")); var_dump(rmdir("mkdir-002/subdir")); var_dump(rmdir("mkdir-002")); var_dump(mkdir("./mkdir-002", 0777)); var_dump(mkdir("./mkdir-002/subdir", 0777)); -var_dump(`ls -l ./mkdir-002`); +var_dump(shell_exec("ls -l ./mkdir-002")); var_dump(rmdir("./mkdir-002/subdir")); var_dump(rmdir("./mkdir-002")); @@ -25,7 +25,7 @@ var_dump(mkdir(__DIR__."/mkdir-002", 0777)); var_dump(mkdir(__DIR__."/mkdir-002/subdir", 0777)); $dirname = __DIR__."/mkdir-002"; $dirname_escaped = escapeshellarg($dirname); -var_dump(`ls -l $dirname_escaped`); +var_dump(shell_exec("ls -l $dirname_escaped")); var_dump(rmdir(__DIR__."/mkdir-002/subdir")); var_dump(rmdir(__DIR__."/mkdir-002")); diff --git a/ext/standard/tests/file/parse_ini_file_variation3.phpt b/ext/standard/tests/file/parse_ini_file_variation3.phpt index 29e620dc8da3e..8485e8d01ef01 100644 --- a/ext/standard/tests/file/parse_ini_file_variation3.phpt +++ b/ext/standard/tests/file/parse_ini_file_variation3.phpt @@ -35,7 +35,6 @@ display_startup_errors = Off log_errors = Off ignore_repeated_errors = Off ignore_repeated_source = Off -report_memleaks = On docref_root = "/phpmanual/" docref_ext = .html @@ -68,7 +67,7 @@ foreach($newdirs as $newdir) { --EXPECTF-- *** Testing parse_ini_file() : variation *** New include path is : %sparse_ini_file_variation3.dir1%sparse_ini_file_variation3.dir2%sparse_ini_file_variation3.dir3%S -array(9) { +array(8) { ["error_reporting"]=> string(5) "30719" ["display_errors"]=> @@ -81,8 +80,6 @@ array(9) { string(0) "" ["ignore_repeated_source"]=> string(0) "" - ["report_memleaks"]=> - string(1) "1" ["docref_root"]=> string(11) "/phpmanual/" ["docref_ext"]=> diff --git a/ext/standard/tests/file/popen_pclose_basic-win32-mb.phpt b/ext/standard/tests/file/popen_pclose_basic-win32-mb.phpt index 7bb4c1be02c77..b0a28055893ab 100644 --- a/ext/standard/tests/file/popen_pclose_basic-win32-mb.phpt +++ b/ext/standard/tests/file/popen_pclose_basic-win32-mb.phpt @@ -35,8 +35,8 @@ $sysroot = exec('echo %SYSTEMROOT%'); $file_handle = popen("$sysroot/system32/sort", "w"); $newline = "\n"; foreach($arr as $str) { - fwrite($file_handle, (binary)$str); - fwrite($file_handle, (binary)(binary)(binary)(binary)(binary)(binary)(binary)(binary)(binary)$newline); + fwrite($file_handle, $str); + fwrite($file_handle, $newline); } pclose($file_handle); diff --git a/ext/standard/tests/file/popen_pclose_basic-win32.phpt b/ext/standard/tests/file/popen_pclose_basic-win32.phpt index 61f2fa302bf98..e5f155be32993 100644 --- a/ext/standard/tests/file/popen_pclose_basic-win32.phpt +++ b/ext/standard/tests/file/popen_pclose_basic-win32.phpt @@ -35,8 +35,8 @@ $sysroot = exec('echo %SYSTEMROOT%'); $file_handle = popen("$sysroot/system32/sort", "w"); $newline = "\n"; foreach($arr as $str) { - fwrite($file_handle, (binary)$str); - fwrite($file_handle, (binary)(binary)(binary)(binary)(binary)(binary)(binary)(binary)(binary)$newline); + fwrite($file_handle, $str); + fwrite($file_handle, $newline); } pclose($file_handle); diff --git a/ext/standard/tests/file/userstreams_005.phpt b/ext/standard/tests/file/userstreams_005.phpt index 8d37040e1950b..11dc8d45b0cd6 100644 --- a/ext/standard/tests/file/userstreams_005.phpt +++ b/ext/standard/tests/file/userstreams_005.phpt @@ -65,5 +65,5 @@ ftruncate(): Argument #2 ($size) must be greater than or equal to 0 ------ stream_truncate bad return: ------- truncation with new_size=0 -Warning: ftruncate(): test_wrapper_bad::stream_truncate did not return a boolean! in %s on line %d +Warning: ftruncate(): test_wrapper_bad::stream_truncate value must be of type bool, string given in %s on line %d bool(false) diff --git a/ext/standard/tests/filters/oss_fuzz_385993744.phpt b/ext/standard/tests/filters/oss_fuzz_385993744.phpt new file mode 100644 index 0000000000000..bfed9e57a9185 --- /dev/null +++ b/ext/standard/tests/filters/oss_fuzz_385993744.phpt @@ -0,0 +1,28 @@ +--TEST-- +OSS-Fuzz #385993744 +--FILE-- +data .= $bucket->data; + } + + $bucket = stream_bucket_new($this->stream, $this->data); + stream_bucket_append($out, $bucket); + + return PSFS_FEED_ME; + } +} +stream_filter_register('sample.filter', SampleFilter::class); +var_dump(file_get_contents('php://filter/read=sample.filter/resource='. __FILE__)); + +?> +--EXPECT-- +string(0) "" diff --git a/ext/standard/tests/general_functions/bug43293_1.phpt b/ext/standard/tests/general_functions/bug43293_1.phpt index c1f618f2bd0e6..fce2ac482cd86 100644 --- a/ext/standard/tests/general_functions/bug43293_1.phpt +++ b/ext/standard/tests/general_functions/bug43293_1.phpt @@ -21,4 +21,5 @@ array(3) { [2]=> int(3) } -bool(false) +array(0) { +} diff --git a/ext/standard/tests/http/bug75535.phpt b/ext/standard/tests/http/bug75535.phpt index 94348d1a027aa..6f16baa242ffb 100644 --- a/ext/standard/tests/http/bug75535.phpt +++ b/ext/standard/tests/http/bug75535.phpt @@ -15,7 +15,7 @@ $responses = array( ['pid' => $pid, 'uri' => $uri] = http_server($responses, $output); var_dump(file_get_contents($uri)); -var_dump($http_response_header); +var_dump(http_get_last_response_headers()); http_server_kill($pid); diff --git a/ext/standard/tests/http/bug80838.phpt b/ext/standard/tests/http/bug80838.phpt index 7171ad173fb6e..8e7578ca025de 100644 --- a/ext/standard/tests/http/bug80838.phpt +++ b/ext/standard/tests/http/bug80838.phpt @@ -33,7 +33,8 @@ var_dump(http_get_last_response_headers()); http_server_kill($pid); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 23 NULL array(3) { [0]=> diff --git a/ext/standard/tests/http/gh9316.phpt b/ext/standard/tests/http/gh9316.phpt index 2f4a637f83e3b..355769d5db1b2 100644 --- a/ext/standard/tests/http/gh9316.phpt +++ b/ext/standard/tests/http/gh9316.phpt @@ -30,7 +30,8 @@ for ($i = 0; $i < count($responses); ++$i) { http_server_kill($pid); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 17 http_get_last_response_headers() before stream layer call: NULL $http_response_header diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt index 744cff9cc72f2..73e1408c370bd 100644 --- a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt +++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-001.phpt @@ -36,7 +36,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt index bc71fd4e41167..cde5aff0afe17 100644 --- a/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt +++ b/ext/standard/tests/http/ghsa-52jp-hrpf-2jff-002.phpt @@ -36,7 +36,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt index c40123560ef1e..0bd496ca72d00 100644 --- a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt +++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-001.phpt @@ -33,7 +33,7 @@ $clientCode = <<<'CODE' ]; $ctx = stream_context_create($opts); var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx)))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt index f3302d77c1d63..d470cdda3f5c8 100644 --- a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt +++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-002.phpt @@ -33,7 +33,7 @@ $clientCode = <<<'CODE' ]; $ctx = stream_context_create($opts); var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx)))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt index 30d20f855419c..594dc8d14e358 100644 --- a/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt +++ b/ext/standard/tests/http/ghsa-hgf5-96fm-v528-003.phpt @@ -33,7 +33,7 @@ $clientCode = <<<'CODE' ]; $ctx = stream_context_create($opts); var_dump(explode("\r\n", base64_decode(file_get_contents("http://user:pwd@{{ ADDR }}", false, $ctx)))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt index bb7945ce62d0e..471f44745ed32 100644 --- a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt +++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-001.phpt @@ -32,7 +32,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt index 1d0e4fa70a2c9..67ce5517ce3c1 100644 --- a/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt +++ b/ext/standard/tests/http/ghsa-pcmh-g36c-qc44-002.phpt @@ -32,7 +32,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt index f935b5a02ca94..94439534d9a5c 100644 --- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-001.phpt @@ -32,7 +32,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt index 078d605b6718f..6ad3e1bc2ca33 100644 --- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-002.phpt @@ -32,7 +32,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt index ad5ddc879cead..497d6d92fbd26 100644 --- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-003.phpt @@ -32,7 +32,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(trim(file_get_contents("http://{{ ADDR }}", false, $ctx))); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt index d0396e819fbd3..e6382420954f3 100644 --- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-004.phpt @@ -32,7 +32,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt index 037d2002cc537..c0ee01671460b 100644 --- a/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt +++ b/ext/standard/tests/http/ghsa-v8xr-gpvj-cx9g-005.phpt @@ -32,7 +32,7 @@ $clientCode = <<<'CODE' $ctx = stream_context_create(); stream_context_set_params($ctx, array("notification" => "stream_notification_callback")); var_dump(file_get_contents("http://{{ ADDR }}", false, $ctx)); - var_dump($http_response_header); + var_dump(http_get_last_response_headers()); CODE; include sprintf("%s/../../../openssl/tests/ServerClientTestCase.inc", __DIR__); diff --git a/ext/standard/tests/http/http_response_header_01.phpt b/ext/standard/tests/http/http_response_header_01.phpt index 4c494f0960ff3..324e00adf7702 100644 --- a/ext/standard/tests/http/http_response_header_01.phpt +++ b/ext/standard/tests/http/http_response_header_01.phpt @@ -24,7 +24,8 @@ var_dump(http_get_last_response_headers()); http_server_kill($pid); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 14 NULL string(4) "Body" array(3) { diff --git a/ext/standard/tests/http/http_response_header_02.phpt b/ext/standard/tests/http/http_response_header_02.phpt index 56eb2868b6d1b..779edfcac1eb3 100644 --- a/ext/standard/tests/http/http_response_header_02.phpt +++ b/ext/standard/tests/http/http_response_header_02.phpt @@ -26,7 +26,8 @@ var_dump(http_get_last_response_headers()); http_server_kill($pid); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 16 NULL string(4) "Body" array(5) { diff --git a/ext/standard/tests/http/http_response_header_03.phpt b/ext/standard/tests/http/http_response_header_03.phpt index f7fa7e00c60aa..5bddc304c7241 100644 --- a/ext/standard/tests/http/http_response_header_03.phpt +++ b/ext/standard/tests/http/http_response_header_03.phpt @@ -27,6 +27,7 @@ http_server_kill($pid); ?> --EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 16 NULL Warning: file_get_contents(http://%s:%d): Failed to open stream: HTTP request failed! HTTP/1.0 404 Not Found%a diff --git a/ext/standard/tests/http/http_response_header_04.phpt b/ext/standard/tests/http/http_response_header_04.phpt index a8a285fb7ad93..5cc6920b610ce 100644 --- a/ext/standard/tests/http/http_response_header_04.phpt +++ b/ext/standard/tests/http/http_response_header_04.phpt @@ -24,7 +24,9 @@ var_dump(http_get_last_response_headers()); http_server_kill($pid); ?> ---EXPECT-- + +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 14 NULL string(4) "Body" array(2) { diff --git a/ext/standard/tests/http/http_response_header_deprecated_bypass.phpt b/ext/standard/tests/http/http_response_header_deprecated_bypass.phpt new file mode 100644 index 0000000000000..91f1957737a6d --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_bypass.phpt @@ -0,0 +1,40 @@ +--TEST-- +Ensure suggested cross-version compatible code for $http_reponse_header provided by the RFC works +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +--FILE-- + $pid, 'uri' => $uri] = http_server($responses, $output); + +var_dump(http_get_last_response_headers()); + +$f = file_get_contents($uri); +var_dump($f); + +if (function_exists('http_get_last_response_headers')) { + $http_response_header = http_get_last_response_headers(); +} +var_dump($http_response_header); + +http_server_kill($pid); + +?> +--EXPECT-- +NULL +string(4) "Body" +array(3) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(12) "Some: Header" + [2]=> + string(12) "Some: Header" +} diff --git a/ext/standard/tests/http/http_response_header_deprecated_multiple_files.phpt b/ext/standard/tests/http/http_response_header_deprecated_multiple_files.phpt new file mode 100644 index 0000000000000..826ec554bf9b6 --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_multiple_files.phpt @@ -0,0 +1,33 @@ +--TEST-- +$http_reponse_header should warn once per file +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +--FILE-- + +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %shttp_response_header_deprecated_multiple_files_1.inc on line %d +string(6) "Body11" +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(13) "Some: Header1" +} + +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %shttp_response_header_deprecated_multiple_files_2.inc on line %d +string(5) "Body2" +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(13) "Some: Header2" +} diff --git a/ext/standard/tests/http/http_response_header_deprecated_multiple_files_1.inc b/ext/standard/tests/http/http_response_header_deprecated_multiple_files_1.inc new file mode 100644 index 0000000000000..68d0ff31729a4 --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_multiple_files_1.inc @@ -0,0 +1,13 @@ + $pid, 'uri' => $uri] = http_server($responses, $output); + +$f = file_get_contents($uri); +var_dump($f); +var_dump($http_response_header); + +http_server_kill($pid); diff --git a/ext/standard/tests/http/http_response_header_deprecated_multiple_files_2.inc b/ext/standard/tests/http/http_response_header_deprecated_multiple_files_2.inc new file mode 100644 index 0000000000000..ba00ff7a06be5 --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_multiple_files_2.inc @@ -0,0 +1,13 @@ + $pid, 'uri' => $uri] = http_server($responses, $output); + +$f = file_get_contents($uri); +var_dump($f); +var_dump($http_response_header); + +http_server_kill($pid); diff --git a/ext/standard/tests/http/http_response_header_deprecated_multiple_op_arrays.phpt b/ext/standard/tests/http/http_response_header_deprecated_multiple_op_arrays.phpt new file mode 100644 index 0000000000000..aa2334dad6d71 --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_multiple_op_arrays.phpt @@ -0,0 +1,20 @@ +--TEST-- +$http_reponse_header should warn once per oparray +--FILE-- + +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 4 + +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 9 diff --git a/ext/standard/tests/http/http_response_header_deprecated_nested_op_arrays.phpt b/ext/standard/tests/http/http_response_header_deprecated_nested_op_arrays.phpt new file mode 100644 index 0000000000000..0f05e689c3412 --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_nested_op_arrays.phpt @@ -0,0 +1,16 @@ +--TEST-- +$http_reponse_header should warn once per oparray even if nested +--FILE-- + +--EXPECTF-- +Deprecated: The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead in %s on line 6 diff --git a/ext/standard/tests/http/http_response_header_deprecated_parameter.phpt b/ext/standard/tests/http/http_response_header_deprecated_parameter.phpt new file mode 100644 index 0000000000000..1dd032a30527e --- /dev/null +++ b/ext/standard/tests/http/http_response_header_deprecated_parameter.phpt @@ -0,0 +1,14 @@ +--TEST-- +$http_reponse_header as a parameter name should not warn +--FILE-- + +--EXPECT-- +string(2) "OK" diff --git a/ext/standard/tests/image/bug13213.phpt b/ext/standard/tests/image/bug13213.phpt index 61fe245efed29..dd5821a830358 100644 --- a/ext/standard/tests/image/bug13213.phpt +++ b/ext/standard/tests/image/bug13213.phpt @@ -6,7 +6,7 @@ var_dump(GetImageSize(__DIR__.'/bug13213.jpg')); ?> --EXPECTF-- Warning: getimagesize(): Corrupt JPEG data: 2 extraneous bytes before marker in %s%ebug13213.php on line %d -array(7) { +array(9) { [0]=> int(1) [1]=> @@ -21,4 +21,8 @@ array(7) { int(3) ["mime"]=> string(10) "image/jpeg" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } diff --git a/ext/standard/tests/image/bug70052.phpt b/ext/standard/tests/image/bug70052.phpt index 76ebda92b220f..252f8921e2925 100644 --- a/ext/standard/tests/image/bug70052.phpt +++ b/ext/standard/tests/image/bug70052.phpt @@ -7,7 +7,7 @@ var_dump(getimagesize(__DIR__ . '/bug70052_2.wbmp')); ?> --EXPECT-- bool(false) -array(5) { +array(7) { [0]=> int(3) [1]=> @@ -18,4 +18,8 @@ array(5) { string(20) "width="3" height="3"" ["mime"]=> string(18) "image/vnd.wap.wbmp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } diff --git a/ext/standard/tests/image/bug70096.phpt b/ext/standard/tests/image/bug70096.phpt index 53ceddea06a86..757287d5aed2c 100644 --- a/ext/standard/tests/image/bug70096.phpt +++ b/ext/standard/tests/image/bug70096.phpt @@ -11,7 +11,6 @@ if (!function_exists('imagejpeg')) die('skip imagejpeg not available'); $filename = __DIR__ . '/bug70096.jpg'; $im = imagecreatetruecolor(10, 10); imagejpeg($im, $filename); -imagedestroy($im); $data = "\x1C\x02x\x00\x0ATest image" . "\x1C\x02t\x00\x22Copyright 2008-2009, The PHP Group"; $content1 = iptcembed($data, $filename); diff --git a/ext/standard/tests/image/bug71848.phpt b/ext/standard/tests/image/bug71848.phpt index 25c05689e6e9c..1c15c87011cf6 100644 --- a/ext/standard/tests/image/bug71848.phpt +++ b/ext/standard/tests/image/bug71848.phpt @@ -6,7 +6,7 @@ var_dump(getimagesize(__DIR__ . '/bug71848.jpg', $info)); var_dump(array_keys($info)); ?> --EXPECT-- -array(7) { +array(9) { [0]=> int(8) [1]=> @@ -21,6 +21,10 @@ array(7) { int(3) ["mime"]=> string(10) "image/jpeg" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(2) { [0]=> diff --git a/ext/standard/tests/image/bug72278.phpt b/ext/standard/tests/image/bug72278.phpt index 074338c18aebc..21079246a5d75 100644 --- a/ext/standard/tests/image/bug72278.phpt +++ b/ext/standard/tests/image/bug72278.phpt @@ -8,7 +8,7 @@ var_dump(getimagesize(FILENAME)); ?> --EXPECTF-- Warning: getimagesize(): Corrupt JPEG data: 3 extraneous bytes before marker in %s%ebug72278.php on line %d -array(7) { +array(9) { [0]=> int(300) [1]=> @@ -23,4 +23,8 @@ array(7) { int(3) ["mime"]=> string(10) "image/jpeg" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } diff --git a/ext/standard/tests/image/bug75708.phpt b/ext/standard/tests/image/bug75708.phpt index 3c81c67cf5ddb..b1a5ee6116c7a 100644 --- a/ext/standard/tests/image/bug75708.phpt +++ b/ext/standard/tests/image/bug75708.phpt @@ -41,7 +41,7 @@ var_dump(getimagesize('fs://bug75708.jpg', $info)); ?> --EXPECT-- -array(7) { +array(9) { [0]=> int(10) [1]=> @@ -56,5 +56,8 @@ array(7) { int(3) ["mime"]=> string(10) "image/jpeg" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } - diff --git a/ext/standard/tests/image/getimagesize.phpt b/ext/standard/tests/image/getimagesize.phpt index 472be1d25e366..81c4f8dc6b5ca 100644 --- a/ext/standard/tests/image/getimagesize.phpt +++ b/ext/standard/tests/image/getimagesize.phpt @@ -23,9 +23,9 @@ GetImageSize() var_dump($result); ?> --EXPECT-- -array(17) { +array(18) { ["test-1pix.bmp"]=> - array(6) { + array(8) { [0]=> int(1) [1]=> @@ -38,9 +38,13 @@ array(17) { int(24) ["mime"]=> string(9) "image/bmp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test12pix.webp"]=> - array(6) { + array(8) { [0]=> int(4) [1]=> @@ -53,9 +57,13 @@ array(17) { int(8) ["mime"]=> string(10) "image/webp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test1bpix.bmp"]=> - array(6) { + array(8) { [0]=> int(1) [1]=> @@ -68,9 +76,13 @@ array(17) { int(32) ["mime"]=> string(9) "image/bmp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test1pix.avif"]=> - array(7) { + array(9) { [0]=> int(102) [1]=> @@ -85,9 +97,13 @@ array(17) { int(4) ["mime"]=> string(10) "image/avif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test1pix.bmp"]=> - array(6) { + array(8) { [0]=> int(1) [1]=> @@ -100,9 +116,13 @@ array(17) { int(24) ["mime"]=> string(9) "image/bmp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test1pix.jp2"]=> - array(7) { + array(9) { [0]=> int(1) [1]=> @@ -117,9 +137,13 @@ array(17) { int(3) ["mime"]=> string(9) "image/jp2" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test1pix.jpc"]=> - array(7) { + array(9) { [0]=> int(1) [1]=> @@ -134,9 +158,13 @@ array(17) { int(3) ["mime"]=> string(24) "application/octet-stream" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test1pix.jpg"]=> - array(7) { + array(9) { [0]=> int(1) [1]=> @@ -151,9 +179,13 @@ array(17) { int(3) ["mime"]=> string(10) "image/jpeg" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test2pix.gif"]=> - array(7) { + array(9) { [0]=> int(2) [1]=> @@ -168,9 +200,13 @@ array(17) { int(3) ["mime"]=> string(9) "image/gif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test3llpix.webp"]=> - array(6) { + array(8) { [0]=> int(1) [1]=> @@ -183,9 +219,13 @@ array(17) { int(8) ["mime"]=> string(10) "image/webp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test3pix.webp"]=> - array(6) { + array(8) { [0]=> int(1) [1]=> @@ -198,9 +238,13 @@ array(17) { int(8) ["mime"]=> string(10) "image/webp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test4pix.gif"]=> - array(7) { + array(9) { [0]=> int(4) [1]=> @@ -215,9 +259,34 @@ array(17) { int(3) ["mime"]=> string(9) "image/gif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" + } + ["test4pix.heic"]=> + array(9) { + [0]=> + int(54) + [1]=> + int(84) + [2]=> + int(20) + [3]=> + string(22) "width="54" height="84"" + ["bits"]=> + int(8) + ["channels"]=> + int(3) + ["mime"]=> + string(10) "image/heif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test4pix.iff"]=> - array(6) { + array(8) { [0]=> int(4) [1]=> @@ -230,9 +299,13 @@ array(17) { int(4) ["mime"]=> string(9) "image/iff" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test4pix.png"]=> - array(6) { + array(8) { [0]=> int(4) [1]=> @@ -245,9 +318,13 @@ array(17) { int(4) ["mime"]=> string(9) "image/png" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test4pix.psd"]=> - array(5) { + array(7) { [0]=> int(4) [1]=> @@ -258,9 +335,13 @@ array(17) { string(20) "width="4" height="1"" ["mime"]=> string(9) "image/psd" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test4pix.swf"]=> - array(5) { + array(7) { [0]=> int(550) [1]=> @@ -271,9 +352,13 @@ array(17) { string(24) "width="550" height="400"" ["mime"]=> string(29) "application/x-shockwave-flash" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ["test4pix.tiff"]=> - array(5) { + array(7) { [0]=> int(4) [1]=> @@ -284,5 +369,9 @@ array(17) { string(20) "width="4" height="1"" ["mime"]=> string(10) "image/tiff" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } } diff --git a/ext/standard/tests/image/getimagesize_246x247.phpt b/ext/standard/tests/image/getimagesize_246x247.phpt index c716ac3aebc08..abf5bec0412a8 100644 --- a/ext/standard/tests/image/getimagesize_246x247.phpt +++ b/ext/standard/tests/image/getimagesize_246x247.phpt @@ -25,7 +25,7 @@ GetImageSize() with 246x247 pixels --EXPECT-- array(1) { ["246x247.png"]=> - array(6) { + array(8) { [0]=> int(246) [1]=> @@ -38,5 +38,9 @@ array(1) { int(4) ["mime"]=> string(9) "image/png" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } } diff --git a/ext/standard/tests/image/getimagesize_256_ico.phpt b/ext/standard/tests/image/getimagesize_256_ico.phpt index 770985c6aec54..7f1fff07a3a25 100644 --- a/ext/standard/tests/image/getimagesize_256_ico.phpt +++ b/ext/standard/tests/image/getimagesize_256_ico.phpt @@ -9,7 +9,7 @@ var_dump(getimagesize(__DIR__ . "/32x256.ico")); ===DONE=== --EXPECT-- *** Testing getimagesize() : 256px ico *** -array(6) { +array(8) { [0]=> int(32) [1]=> @@ -22,5 +22,9 @@ array(6) { int(8) ["mime"]=> string(24) "image/vnd.microsoft.icon" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } ===DONE=== diff --git a/ext/standard/tests/image/getimagesize_384x385.phpt b/ext/standard/tests/image/getimagesize_384x385.phpt index 57dc8a7192159..69705080cad02 100644 --- a/ext/standard/tests/image/getimagesize_384x385.phpt +++ b/ext/standard/tests/image/getimagesize_384x385.phpt @@ -25,7 +25,7 @@ GetImageSize() with 384x385 pixels --EXPECT-- array(1) { ["384x385.png"]=> - array(6) { + array(8) { [0]=> int(384) [1]=> @@ -38,5 +38,9 @@ array(1) { int(1) ["mime"]=> string(9) "image/png" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } } diff --git a/ext/standard/tests/image/getimagesize_basic.phpt b/ext/standard/tests/image/getimagesize_basic.phpt index f1a6d108d31bd..3dd1823437c20 100644 --- a/ext/standard/tests/image/getimagesize_basic.phpt +++ b/ext/standard/tests/image/getimagesize_basic.phpt @@ -44,7 +44,7 @@ foreach($imagetype_filenames as $key => $filename) { *** Testing getimagesize() : basic functionality *** -- GIF image file (200x100.gif) -- -array(7) { +array(9) { [0]=> int(200) [1]=> @@ -59,12 +59,16 @@ array(7) { int(3) ["mime"]=> string(9) "image/gif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } -- JPEG image file (200x100.jpg) -- -array(7) { +array(9) { [0]=> int(200) [1]=> @@ -79,6 +83,10 @@ array(7) { int(3) ["mime"]=> string(10) "image/jpeg" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(1) { ["APP0"]=> @@ -86,7 +94,7 @@ array(1) { } -- PNG image file (200x100.png) -- -array(6) { +array(8) { [0]=> int(200) [1]=> @@ -99,12 +107,16 @@ array(6) { int(8) ["mime"]=> string(9) "image/png" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } -- SWF image file (200x100.swf) -- -array(5) { +array(7) { [0]=> int(200) [1]=> @@ -115,12 +127,16 @@ array(5) { string(24) "width="200" height="100"" ["mime"]=> string(29) "application/x-shockwave-flash" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } -- BMP image file (200x100.bmp) -- -array(6) { +array(8) { [0]=> int(200) [1]=> @@ -133,12 +149,16 @@ array(6) { int(24) ["mime"]=> string(9) "image/bmp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } -- TIFF intel byte order image file (200x100.tiff) -- -array(5) { +array(7) { [0]=> int(200) [1]=> @@ -149,12 +169,16 @@ array(5) { string(24) "width="200" height="100"" ["mime"]=> string(10) "image/tiff" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } -- JPC image file (test1pix.jpc) -- -array(7) { +array(9) { [0]=> int(1) [1]=> @@ -169,12 +193,16 @@ array(7) { int(3) ["mime"]=> string(24) "application/octet-stream" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } -- JP2 image file (test1pix.jp2) -- -array(7) { +array(9) { [0]=> int(1) [1]=> @@ -189,12 +217,16 @@ array(7) { int(3) ["mime"]=> string(9) "image/jp2" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } -- IFF image file (test4pix.iff) -- -array(6) { +array(8) { [0]=> int(4) [1]=> @@ -207,6 +239,10 @@ array(6) { int(4) ["mime"]=> string(9) "image/iff" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } diff --git a/ext/standard/tests/image/getimagesize_swc.phpt b/ext/standard/tests/image/getimagesize_swc.phpt index 7dff107d477ee..f5031e7a223c7 100644 --- a/ext/standard/tests/image/getimagesize_swc.phpt +++ b/ext/standard/tests/image/getimagesize_swc.phpt @@ -13,7 +13,7 @@ if (!defined("IMAGETYPE_SWC")) { var_dump(getimagesize(__DIR__ . "/test13pix.swf")); ?> --EXPECT-- -array(5) { +array(7) { [0]=> int(550) [1]=> @@ -24,4 +24,8 @@ array(5) { string(24) "width="550" height="400"" ["mime"]=> string(29) "application/x-shockwave-flash" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } diff --git a/ext/standard/tests/image/getimagesize_tif_mm.phpt b/ext/standard/tests/image/getimagesize_tif_mm.phpt index cd6f32f4d3785..58047f6134dc4 100644 --- a/ext/standard/tests/image/getimagesize_tif_mm.phpt +++ b/ext/standard/tests/image/getimagesize_tif_mm.phpt @@ -9,7 +9,7 @@ var_dump($arr); ?> --EXPECT-- *** Testing getimagesize() : tiff_mm format *** -array(5) { +array(7) { [0]=> int(2) [1]=> @@ -20,6 +20,10 @@ array(5) { string(20) "width="2" height="2"" ["mime"]=> string(10) "image/tiff" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } diff --git a/ext/standard/tests/image/getimagesize_variation4.phpt b/ext/standard/tests/image/getimagesize_variation4.phpt index 658ce84d518cb..49b924ffe77b9 100644 --- a/ext/standard/tests/image/getimagesize_variation4.phpt +++ b/ext/standard/tests/image/getimagesize_variation4.phpt @@ -17,7 +17,7 @@ var_dump( $info ); ?> --EXPECT-- *** Testing getimagesize() : variation *** -array(5) { +array(7) { [0]=> int(550) [1]=> @@ -28,6 +28,10 @@ array(5) { string(24) "width="550" height="400"" ["mime"]=> string(29) "application/x-shockwave-flash" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } diff --git a/ext/standard/tests/image/getimagesize_variation_005.phpt b/ext/standard/tests/image/getimagesize_variation_005.phpt index 8e471e50a23a7..c6d083b23b5e4 100644 --- a/ext/standard/tests/image/getimagesize_variation_005.phpt +++ b/ext/standard/tests/image/getimagesize_variation_005.phpt @@ -17,7 +17,7 @@ var_dump( $info ); ?> --EXPECT-- *** Testing getimagesize() : basic functionality *** -array(5) { +array(7) { [0]=> int(550) [1]=> @@ -28,6 +28,10 @@ array(5) { string(24) "width="550" height="400"" ["mime"]=> string(29) "application/x-shockwave-flash" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } diff --git a/ext/standard/tests/image/getimagesize_wbmp.phpt b/ext/standard/tests/image/getimagesize_wbmp.phpt index 0b0ebe52347d9..97151d8412460 100644 --- a/ext/standard/tests/image/getimagesize_wbmp.phpt +++ b/ext/standard/tests/image/getimagesize_wbmp.phpt @@ -9,7 +9,7 @@ var_dump($arr); ?> --EXPECT-- *** Testing getimagesize() : wbmp format *** -array(5) { +array(7) { [0]=> int(75) [1]=> @@ -20,6 +20,10 @@ array(5) { string(22) "width="75" height="50"" ["mime"]=> string(18) "image/vnd.wap.wbmp" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } diff --git a/ext/standard/tests/image/getimagesize_xbm.phpt b/ext/standard/tests/image/getimagesize_xbm.phpt index 5ecd6ad206348..4f7f7965dd657 100644 --- a/ext/standard/tests/image/getimagesize_xbm.phpt +++ b/ext/standard/tests/image/getimagesize_xbm.phpt @@ -9,7 +9,7 @@ var_dump($arr); ?> --EXPECT-- *** Testing getimagesize() : xbm format *** -array(5) { +array(7) { [0]=> int(75) [1]=> @@ -20,6 +20,10 @@ array(5) { string(22) "width="75" height="50"" ["mime"]=> string(9) "image/xbm" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } array(0) { } diff --git a/ext/standard/tests/image/getimagesizefromstring1.phpt b/ext/standard/tests/image/getimagesizefromstring1.phpt index 6202b38e89654..0037c292f7009 100644 --- a/ext/standard/tests/image/getimagesizefromstring1.phpt +++ b/ext/standard/tests/image/getimagesizefromstring1.phpt @@ -14,7 +14,7 @@ var_dump($i1); var_dump($i2); ?> --EXPECT-- -array(7) { +array(9) { [0]=> int(120) [1]=> @@ -29,8 +29,12 @@ array(7) { int(3) ["mime"]=> string(9) "image/gif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } -array(7) { +array(9) { [0]=> int(120) [1]=> @@ -45,4 +49,8 @@ array(7) { int(3) ["mime"]=> string(9) "image/gif" + ["width_unit"]=> + string(2) "px" + ["height_unit"]=> + string(2) "px" } diff --git a/ext/standard/tests/image/image_type_to_extension.phpt b/ext/standard/tests/image/image_type_to_extension.phpt index 9b0d991d070f7..3f3e5f280511d 100644 --- a/ext/standard/tests/image/image_type_to_extension.phpt +++ b/ext/standard/tests/image/image_type_to_extension.phpt @@ -25,6 +25,7 @@ image_type_to_extension() "IMAGETYPE_XBM" => IMAGETYPE_XBM, "IMAGETYPE_WEBP" => IMAGETYPE_WEBP, "IMAGETYPE_AVIF" => IMAGETYPE_AVIF, + "IMAGETYPE_HEIF" => IMAGETYPE_HEIF, ); foreach($constants as $name => $constant) { printf("Constant: %s\n\tWith dot: %s\n\tWithout dot: %s\n", $name, image_type_to_extension($constant), image_type_to_extension($constant, false)); @@ -89,6 +90,9 @@ Constant: IMAGETYPE_WEBP Constant: IMAGETYPE_AVIF With dot: .avif Without dot: avif +Constant: IMAGETYPE_HEIF + With dot: .heif + Without dot: heif bool(false) bool(false) Done diff --git a/ext/standard/tests/image/image_type_to_mime_type.phpt b/ext/standard/tests/image/image_type_to_mime_type.phpt index 5877efe531fd9..0102955babe73 100644 --- a/ext/standard/tests/image/image_type_to_mime_type.phpt +++ b/ext/standard/tests/image/image_type_to_mime_type.phpt @@ -24,7 +24,7 @@ image_type_to_mime_type() var_dump($result); ?> --EXPECT-- -array(17) { +array(18) { ["test-1pix.bmp"]=> string(9) "image/bmp" ["test12pix.webp"]=> @@ -49,6 +49,8 @@ array(17) { string(10) "image/webp" ["test4pix.gif"]=> string(9) "image/gif" + ["test4pix.heic"]=> + string(10) "image/heif" ["test4pix.iff"]=> string(9) "image/iff" ["test4pix.png"]=> diff --git a/ext/standard/tests/image/image_type_to_mime_type_basic.phpt b/ext/standard/tests/image/image_type_to_mime_type_basic.phpt index bf5a1ee250990..a393c3e83dc27 100644 --- a/ext/standard/tests/image/image_type_to_mime_type_basic.phpt +++ b/ext/standard/tests/image/image_type_to_mime_type_basic.phpt @@ -21,8 +21,10 @@ $image_types = array ( IMAGETYPE_IFF, IMAGETYPE_WBMP, IMAGETYPE_JPEG2000, + IMAGETYPE_HEIF, IMAGETYPE_XBM, - IMAGETYPE_WEBP + IMAGETYPE_WEBP, + IMAGETYPE_HEIF, ); foreach($image_types as $image_type) { @@ -49,7 +51,9 @@ string(24) "application/octet-stream" string(9) "image/iff" string(18) "image/vnd.wap.wbmp" string(24) "application/octet-stream" +string(10) "image/heif" string(9) "image/xbm" string(10) "image/webp" +string(10) "image/heif" Done image_type_to_mime_type() test diff --git a/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt b/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt index fc17cb5ecd947..8bd62188d216c 100644 --- a/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt +++ b/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt @@ -1,78 +1,84 @@ --TEST-- -image_type_to_mime_type() (passinf equivalent integer values) +image_type_to_mime_type() (passing equivalent integer values) --CREDITS-- Sanjay Mantoor --FILE-- ---EXPECTREGEX-- -\*\*\* Testing image_type_to_mime_type\(\) : usage variations \*\*\* +--EXPECT-- +*** Testing image_type_to_mime_type() : usage variations *** -- Iteration 0 -- -string\(24\) "application\/octet-stream" +string(24) "application/octet-stream" -- Iteration 1 -- -string\(9\) "image\/gif" +string(9) "image/gif" -- Iteration 2 -- -string\(10\) "image\/jpeg" +string(10) "image/jpeg" -- Iteration 3 -- -string\(9\) "image\/png" +string(9) "image/png" -- Iteration 4 -- -string\(29\) "application\/x-shockwave-flash" +string(29) "application/x-shockwave-flash" -- Iteration 5 -- -string\(9\) "image\/psd" +string(9) "image/psd" -- Iteration 6 -- -string\(9\) "image\/bmp" +string(9) "image/bmp" -- Iteration 7 -- -string\(10\) "image\/tiff" +string(10) "image/tiff" -- Iteration 8 -- -string\(10\) "image\/tiff" +string(10) "image/tiff" -- Iteration 9 -- -string\(24\) "application\/octet-stream" +string(24) "application/octet-stream" -- Iteration 10 -- -string\(9\) "image\/jp2" +string(9) "image/jp2" -- Iteration 11 -- -string\(24\) "application\/octet-stream" +string(24) "application/octet-stream" -- Iteration 12 -- -string\(24\) "application\/octet-stream" +string(24) "application/octet-stream" -- Iteration 13 -- -string\(2[49]\) "application\/(x-shockwave-flash|octet-stream)" +string(29) "application/x-shockwave-flash" -- Iteration 14 -- -string\(9\) "image\/iff" +string(9) "image/iff" -- Iteration 15 -- -string\(18\) "image\/vnd.wap.wbmp" +string(18) "image/vnd.wap.wbmp" -- Iteration 16 -- -string\(9\) "image\/xbm" +string(9) "image/xbm" -- Iteration 17 -- -string\(24\) "image\/vnd.microsoft.icon" +string(24) "image/vnd.microsoft.icon" -- Iteration 18 -- -string\(10\) "image\/webp" +string(10) "image/webp" -- Iteration 19 -- -string\(10\) "image\/avif" +string(10) "image/avif" -- Iteration 20 -- -string\(24\) "application\/octet-stream" +string(10) "image/heif" + +-- Iteration 999 -- +string(24) "application/octet-stream" diff --git a/ext/standard/tests/image/test4pix.heic b/ext/standard/tests/image/test4pix.heic new file mode 100644 index 0000000000000..93ca3ed1faf9c Binary files /dev/null and b/ext/standard/tests/image/test4pix.heic differ diff --git a/ext/standard/tests/mail/gh19188_cr_lf_mode.phpt b/ext/standard/tests/mail/gh19188_cr_lf_mode.phpt new file mode 100644 index 0000000000000..15c9aa2aa28ff --- /dev/null +++ b/ext/standard/tests/mail/gh19188_cr_lf_mode.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-19188: new INI mail.cr_lf_mode +--INI-- +sendmail_path={MAIL:gh19188_cr_lf_mode.out} +mail.cr_lf_mode=crlf +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +CRLF mode: +int(5) +int(0) diff --git a/ext/standard/tests/mail/gh19188_invalid_mode.phpt b/ext/standard/tests/mail/gh19188_invalid_mode.phpt new file mode 100644 index 0000000000000..fb1baa3d4702d --- /dev/null +++ b/ext/standard/tests/mail/gh19188_invalid_mode.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-19188: mail.cr_lf_mode runtime changes should fail +--FILE-- + +--EXPECT-- +bool(false) +string(4) "crlf" +bool(false) +string(4) "crlf" +bool(false) +string(4) "crlf" +bool(false) +string(4) "crlf" diff --git a/ext/standard/tests/mail/gh19188_lf_mode.phpt b/ext/standard/tests/mail/gh19188_lf_mode.phpt new file mode 100644 index 0000000000000..bd69cc42b62df --- /dev/null +++ b/ext/standard/tests/mail/gh19188_lf_mode.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=lf +--INI-- +sendmail_path={MAIL:gh19188_lf_mode.out} +mail.cr_lf_mode=lf +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +LF mode: +int(0) +int(6) diff --git a/ext/standard/tests/mail/gh19188_mixed_mode.phpt b/ext/standard/tests/mail/gh19188_mixed_mode.phpt new file mode 100644 index 0000000000000..fa5eb63bd4fe7 --- /dev/null +++ b/ext/standard/tests/mail/gh19188_mixed_mode.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=mixed +--INI-- +sendmail_path={MAIL:gh19188_mixed_mode.out} +mail.cr_lf_mode=mixed +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +Mixed mode: +int(5) diff --git a/ext/standard/tests/mail/gh19188_os_mode_unix.phpt b/ext/standard/tests/mail/gh19188_os_mode_unix.phpt new file mode 100644 index 0000000000000..b365e3a671b03 --- /dev/null +++ b/ext/standard/tests/mail/gh19188_os_mode_unix.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=os (Unix) +--SKIPIF-- + +--INI-- +sendmail_path={MAIL:gh19188_os_mode.out} +mail.cr_lf_mode=os +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +OS mode: +CRLF count: int(0) +LF-only count: int(5) diff --git a/ext/standard/tests/mail/gh19188_os_mode_windows.phpt b/ext/standard/tests/mail/gh19188_os_mode_windows.phpt new file mode 100644 index 0000000000000..c3c3e7c08ee9d --- /dev/null +++ b/ext/standard/tests/mail/gh19188_os_mode_windows.phpt @@ -0,0 +1,31 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=os (Windows) +--SKIPIF-- + +--INI-- +sendmail_path={MAIL:gh19188_os_mode.out} +mail.cr_lf_mode=os +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +OS mode: +CRLF count: int(5) +LF-only count: int(0) diff --git a/ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt b/ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt new file mode 100644 index 0000000000000..7556c3be94ccd --- /dev/null +++ b/ext/standard/tests/network/ghsa-3cr5-j632-f35r.phpt @@ -0,0 +1,21 @@ +--TEST-- +GHSA-3cr5-j632-f35r: Null byte termination in fsockopen() +--FILE-- + +--EXPECTF-- + +Warning: fsockopen(): Unable to connect to localhost:%d (The hostname must not contain null bytes) in %s +bool(false) diff --git a/ext/standard/tests/network/setcookie.phpt b/ext/standard/tests/network/setcookie.phpt index f43680a5bceae..caf9aa9ae0763 100644 --- a/ext/standard/tests/network/setcookie.phpt +++ b/ext/standard/tests/network/setcookie.phpt @@ -19,6 +19,7 @@ setcookie('name', 'value', 0, '', '', FALSE, TRUE); setcookie('name', 'value', ['expires' => $tsp]); setcookie('name', 'value', ['expires' => $tsn, 'path' => '/path/', 'domain' => 'domain.tld', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict']); +setcookie('name', 'value', ['secure' => true, 'partitioned' => true]); $expected = array( 'Set-Cookie: name=deleted; expires='.date('D, d M Y H:i:s', 1).' GMT; Max-Age=0', @@ -34,7 +35,8 @@ $expected = array( 'Set-Cookie: name=value; secure', 'Set-Cookie: name=value; HttpOnly', 'Set-Cookie: name=value; expires='.date('D, d M Y H:i:s', $tsp).' GMT; Max-Age=5', - 'Set-Cookie: name=value; expires='.date('D, d M Y H:i:s', $tsn).' GMT; Max-Age=0; path=/path/; domain=domain.tld; secure; HttpOnly; SameSite=Strict' + 'Set-Cookie: name=value; expires='.date('D, d M Y H:i:s', $tsn).' GMT; Max-Age=0; path=/path/; domain=domain.tld; secure; HttpOnly; SameSite=Strict', + 'Set-Cookie: name=value; secure; Partitioned' ); $headers = headers_list(); diff --git a/ext/standard/tests/network/setcookie_array_option_error.phpt b/ext/standard/tests/network/setcookie_array_option_error.phpt index ad4caf35108fa..0fb2ae011c31a 100644 --- a/ext/standard/tests/network/setcookie_array_option_error.phpt +++ b/ext/standard/tests/network/setcookie_array_option_error.phpt @@ -37,6 +37,12 @@ try { } catch (\ValueError $e) { echo $e->getMessage() . "\n"; } +// Partitioned without secure +try { + setcookie('name', 'value', ['partitioned' => true]); +} catch (\ValueError $e) { + echo $e->getMessage() . "\n"; +} // Arguments after options array (will not be set) try { @@ -66,6 +72,7 @@ setcookie(): option array cannot have numeric keys setcookie(): option "foo" is invalid setcookie(): "path" option cannot contain ",", ";", " ", "\t", "\r", "\n", "\013", or "\014" setcookie(): "domain" option cannot contain ",", ";", " ", "\t", "\r", "\n", "\013", or "\014" +setcookie(): "partitioned" option cannot be used without "secure" option setcookie(): Expects exactly 3 arguments when argument #3 ($expires_or_options) is an array bool(true) array(1) { diff --git a/ext/standard/tests/serialize/001.phpt b/ext/standard/tests/serialize/001.phpt index f2ac0340cf078..b4d2f3e841da5 100644 --- a/ext/standard/tests/serialize/001.phpt +++ b/ext/standard/tests/serialize/001.phpt @@ -1,5 +1,5 @@ --TEST-- -serialize()/unserialize()/var_dump() +serialize()/unserialize()/var_dump() using __sleep() and __wakeup() --INI-- serialize_precision=100 --FILE-- @@ -78,6 +78,9 @@ $a = unserialize($data); var_dump($a); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d N; b:1; b:0; diff --git a/ext/standard/tests/serialize/005.phpt b/ext/standard/tests/serialize/005.phpt index 333c09525883c..c33d6267d6d50 100644 --- a/ext/standard/tests/serialize/005.phpt +++ b/ext/standard/tests/serialize/005.phpt @@ -128,6 +128,14 @@ echo "===AutoNA===\n"; var_dump(unserialize('O:22:"autoload_not_available":0:{}')); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d ===O1=== TestOld::__sleep() diff --git a/ext/standard/tests/serialize/__serialize_004.phpt b/ext/standard/tests/serialize/__serialize_004.phpt index 66db8bf5044be..ef1c8582743f0 100644 --- a/ext/standard/tests/serialize/__serialize_004.phpt +++ b/ext/standard/tests/serialize/__serialize_004.phpt @@ -38,7 +38,8 @@ var_dump($s = serialize($obj)); var_dump(unserialize($s)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d string(126) "O:6:"Wakeup":1:{s:4:"data";a:1:{i:0;O:11:"Unserialize":1:{i:0;O:6:"Wakeup":1:{s:4:"data";a:1:{i:0;O:11:"Unserialize":0:{}}}}}}" __unserialize() called array(0) { diff --git a/ext/standard/tests/serialize/bug14293.phpt b/ext/standard/tests/serialize/bug14293.phpt index c52ced3d0f3d4..5c7b19906c91a 100644 --- a/ext/standard/tests/serialize/bug14293.phpt +++ b/ext/standard/tests/serialize/bug14293.phpt @@ -26,6 +26,7 @@ var_dump($t); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d __sleep called Warning: serialize(): "b" returned as member variable from __sleep() but does not exist in %s on line %d diff --git a/ext/standard/tests/serialize/bug21957.phpt b/ext/standard/tests/serialize/bug21957.phpt index 9d761a6699c96..b3bd73c661ffb 100644 --- a/ext/standard/tests/serialize/bug21957.phpt +++ b/ext/standard/tests/serialize/bug21957.phpt @@ -28,7 +28,8 @@ echo $s . "\n"; var_dump(unserialize($s)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d array(2) { ["one"]=> string(3) "ABC" diff --git a/ext/standard/tests/serialize/bug35895.phpt b/ext/standard/tests/serialize/bug35895.phpt index de7ff6d3e1a4f..003b8eb5f0873 100644 --- a/ext/standard/tests/serialize/bug35895.phpt +++ b/ext/standard/tests/serialize/bug35895.phpt @@ -21,4 +21,8 @@ serialize($obj); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: serialize(): "parents" returned as member variable from __sleep() but does not exist in %s on line %d diff --git a/ext/standard/tests/serialize/bug64354_2.phpt b/ext/standard/tests/serialize/bug64354_2.phpt index 675305132157e..ddb81af8be476 100644 --- a/ext/standard/tests/serialize/bug64354_2.phpt +++ b/ext/standard/tests/serialize/bug64354_2.phpt @@ -20,5 +20,6 @@ try { var_dump($e->getMessage()); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d string(6) "Failed" diff --git a/ext/standard/tests/serialize/bug64354_3.phpt b/ext/standard/tests/serialize/bug64354_3.phpt index e3832e653bbfb..195ca32e376e0 100644 --- a/ext/standard/tests/serialize/bug64354_3.phpt +++ b/ext/standard/tests/serialize/bug64354_3.phpt @@ -26,5 +26,7 @@ try { } ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d string(6) "Failed" diff --git a/ext/standard/tests/serialize/bug65806.phpt b/ext/standard/tests/serialize/bug65806.phpt index 166b694442b78..3059959b1f448 100644 --- a/ext/standard/tests/serialize/bug65806.phpt +++ b/ext/standard/tests/serialize/bug65806.phpt @@ -73,7 +73,10 @@ function check(myObjC $obj) { return 'successful'; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d SCRIPT START check successful start serialize/unserialize diff --git a/ext/standard/tests/serialize/bug68976.phpt b/ext/standard/tests/serialize/bug68976.phpt index 514bd8b453fda..4d60bc6b7feb3 100644 --- a/ext/standard/tests/serialize/bug68976.phpt +++ b/ext/standard/tests/serialize/bug68976.phpt @@ -25,7 +25,8 @@ for($i = 0; $i < 5; $i++) { var_dump($data); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d array(2) { [0]=> object(evilClass)#1 (0) { diff --git a/ext/standard/tests/serialize/bug69210.phpt b/ext/standard/tests/serialize/bug69210.phpt index 41cc8f55f9a5d..30ea71b28deb1 100644 --- a/ext/standard/tests/serialize/bug69210.phpt +++ b/ext/standard/tests/serialize/bug69210.phpt @@ -34,7 +34,10 @@ echo $si . "\n"; var_dump(unserialize($ss)); var_dump(unserialize($si)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d O:10:"testString":1:{s:1:"a";b:1;} O:11:"testInteger":1:{s:1:"a";b:1;} object(testString)#3 (1) { diff --git a/ext/standard/tests/serialize/bug69425.phpt b/ext/standard/tests/serialize/bug69425.phpt index 1bc79c0387c8c..6199ba394b44d 100644 --- a/ext/standard/tests/serialize/bug69425.phpt +++ b/ext/standard/tests/serialize/bug69425.phpt @@ -23,6 +23,7 @@ var_dump($data); ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d int(1) array(2) { [0]=> diff --git a/ext/standard/tests/serialize/bug70172_2.phpt b/ext/standard/tests/serialize/bug70172_2.phpt index 27e77951fe37c..9730d44cfc6ff 100644 --- a/ext/standard/tests/serialize/bug70172_2.phpt +++ b/ext/standard/tests/serialize/bug70172_2.phpt @@ -48,7 +48,9 @@ function ptr2str($ptr) } ?> --EXPECTF-- -Deprecated: %s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: obj implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d array(2) { [0]=> object(obj2)#%d (1) { diff --git a/ext/standard/tests/serialize/bug70513.phpt b/ext/standard/tests/serialize/bug70513.phpt index 9a93a3359b678..c45f61353ffbc 100644 --- a/ext/standard/tests/serialize/bug70513.phpt +++ b/ext/standard/tests/serialize/bug70513.phpt @@ -26,7 +26,8 @@ var_dump($x); var_dump($obj); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d array(1) { [0]=> int(1) diff --git a/ext/standard/tests/serialize/bug71995.phpt b/ext/standard/tests/serialize/bug71995.phpt index 9d51ace750e13..032a198d261a1 100644 --- a/ext/standard/tests/serialize/bug71995.phpt +++ b/ext/standard/tests/serialize/bug71995.phpt @@ -18,6 +18,8 @@ var_dump($s); var_dump(unserialize($s)); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: serialize(): "b" is returned from __sleep() multiple times in %s on line %d string(39) "O:1:"A":1:{s:1:"b";O:8:"stdClass":0:{}}" object(A)#%d (1) { diff --git a/ext/standard/tests/serialize/bug72663.phpt b/ext/standard/tests/serialize/bug72663.phpt index ce767973e97f1..b92f3a1c50426 100644 --- a/ext/standard/tests/serialize/bug72663.phpt +++ b/ext/standard/tests/serialize/bug72663.phpt @@ -49,6 +49,10 @@ try { ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: unserialize(): Error at offset 17 of 24 bytes in %s on line %d bool(false) diff --git a/ext/standard/tests/serialize/bug72731.phpt b/ext/standard/tests/serialize/bug72731.phpt index 9489928cfb128..f13103288873f 100644 --- a/ext/standard/tests/serialize/bug72731.phpt +++ b/ext/standard/tests/serialize/bug72731.phpt @@ -15,4 +15,5 @@ var_dump(unserialize($poc)); ?> --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d %s(73588229205) diff --git a/ext/standard/tests/serialize/bug73154.phpt b/ext/standard/tests/serialize/bug73154.phpt index 8d0f188bf7f34..8caf5a7013c11 100644 --- a/ext/standard/tests/serialize/bug73154.phpt +++ b/ext/standard/tests/serialize/bug73154.phpt @@ -12,5 +12,6 @@ class a { $s = 'a:1:{i:0;O:1:"a":1:{s:1:"a";R:2;}}'; var_dump(serialize(unserialize($s))); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d string(22) "a:1:{i:0;O:1:"a":0:{}}" diff --git a/ext/standard/tests/serialize/bug79526.phpt b/ext/standard/tests/serialize/bug79526.phpt index 440c18772d53d..e2e3154dadae8 100644 --- a/ext/standard/tests/serialize/bug79526.phpt +++ b/ext/standard/tests/serialize/bug79526.phpt @@ -24,6 +24,10 @@ serialize(new B()); ?> Done --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: serialize(): A::__sleep() should return an array only containing the names of instance-variables to serialize in %s on line %d Warning: serialize(): B::__sleep() should return an array only containing the names of instance-variables to serialize in %s on line %d diff --git a/ext/standard/tests/serialize/bug81163.phpt b/ext/standard/tests/serialize/bug81163.phpt index 855fc1c953ed2..a223188b2fd45 100644 --- a/ext/standard/tests/serialize/bug81163.phpt +++ b/ext/standard/tests/serialize/bug81163.phpt @@ -18,4 +18,6 @@ class bar extends foo serialize(new bar()); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: serialize(): bar::__sleep() should return an array only containing the names of instance-variables to serialize in %s on line %d diff --git a/ext/standard/tests/serialize/gh12265.phpt b/ext/standard/tests/serialize/gh12265.phpt new file mode 100644 index 0000000000000..5f49a62fee29f --- /dev/null +++ b/ext/standard/tests/serialize/gh12265.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-12265 (Cloning an object breaks serialization recursion) - __serialize variation +--FILE-- + new A($this)]; + } +} + +class C { + public B $b; + + public function __construct() { + $this->b = new B; + } +} + +$b = new B(); +$sb = serialize($b); +$stb = serialize(new B); + +printf("serialized original: %s\n", $sb); +printf("serialized temp : %s\n", $stb); + +$c = new C; +$sc = serialize($c); +$stc = serialize(new C); + +printf("serialized original: %s\n", $sc); +printf("serialized temp : %s\n", $stc); + +?> +--EXPECT-- +serialized original: O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized temp : O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized original: O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} +serialized temp : O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} diff --git a/ext/standard/tests/serialize/gh12265b.phpt b/ext/standard/tests/serialize/gh12265b.phpt new file mode 100644 index 0000000000000..83c2603d71376 --- /dev/null +++ b/ext/standard/tests/serialize/gh12265b.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-12265 (Cloning an object breaks serialization recursion) - __sleep variation +--FILE-- +a = new A($this); + return ['a']; + } +} + +class C { + public B $b; + + public function __construct() { + $this->b = new B; + } +} + +$b = new B(); +$sb = serialize($b); +$stb = serialize(new B); + +printf("serialized original: %s\n", $sb); +printf("serialized temp : %s\n", $stb); + +$c = new C; +$sc = serialize($c); +$stc = serialize(new C); + +printf("serialized original: %s\n", $sc); +printf("serialized temp : %s\n", $stc); + +?> +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d +serialized original: O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized temp : O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized original: O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} +serialized temp : O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} diff --git a/ext/standard/tests/serialize/gh19701.phpt b/ext/standard/tests/serialize/gh19701.phpt new file mode 100644 index 0000000000000..a8c1d53c6e376 --- /dev/null +++ b/ext/standard/tests/serialize/gh19701.phpt @@ -0,0 +1,31 @@ +--TEST-- +GH-19701 (Serialize/deserialize loses some data) +--CREDITS-- +cuchac +DanielEScherzer +--FILE-- +parent = $baseProduct; +$baseProduct->children = [ $child ]; + +$data = [clone $baseProduct, $baseProduct]; + +echo serialize($data), "\n"; + +?> +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d +a:2:{i:0;O:4:"Item":2:{s:8:"children";a:1:{i:0;O:4:"Item":2:{s:8:"children";a:0:{}s:6:"parent";O:4:"Item":2:{s:8:"children";a:1:{i:0;r:4;}s:6:"parent";N;}}}s:6:"parent";N;}i:1;r:6;} diff --git a/ext/standard/tests/serialize/oss_fuzz_433303828.phpt b/ext/standard/tests/serialize/oss_fuzz_433303828.phpt new file mode 100644 index 0000000000000..fb90b51d4dadf --- /dev/null +++ b/ext/standard/tests/serialize/oss_fuzz_433303828.phpt @@ -0,0 +1,13 @@ +--TEST-- +OSS-Fuzz #433303828 +--FILE-- + +--EXPECTF-- +Warning: unserialize(): Error at offset 9 of 10 bytes in %s on line %d + +Warning: unserialize(): Error at offset 10 of 11 bytes in %s on line %d diff --git a/ext/standard/tests/serialize/sleep_deprecation_promoted_exception.phpt b/ext/standard/tests/serialize/sleep_deprecation_promoted_exception.phpt new file mode 100644 index 0000000000000..e0e32c3b4edc6 --- /dev/null +++ b/ext/standard/tests/serialize/sleep_deprecation_promoted_exception.phpt @@ -0,0 +1,24 @@ +--TEST-- +__sleep() deprecation promoted to exception +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ErrorException: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) diff --git a/ext/standard/tests/serialize/sleep_deprecation_promoted_exception2.inc b/ext/standard/tests/serialize/sleep_deprecation_promoted_exception2.inc new file mode 100644 index 0000000000000..af121bc44d70e --- /dev/null +++ b/ext/standard/tests/serialize/sleep_deprecation_promoted_exception2.inc @@ -0,0 +1,7 @@ +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ErrorException: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) diff --git a/ext/standard/tests/serialize/sleep_deref.phpt b/ext/standard/tests/serialize/sleep_deref.phpt index 36777db0a358c..9beb0ba0dc933 100644 --- a/ext/standard/tests/serialize/sleep_deref.phpt +++ b/ext/standard/tests/serialize/sleep_deref.phpt @@ -14,5 +14,6 @@ class Test { var_dump(serialize(new Test)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d string(28) "O:4:"Test":1:{s:1:"x";i:42;}" diff --git a/ext/standard/tests/serialize/sleep_mangled_name_clash.phpt b/ext/standard/tests/serialize/sleep_mangled_name_clash.phpt index eef5949abbe57..2e4d47c661eef 100644 --- a/ext/standard/tests/serialize/sleep_mangled_name_clash.phpt +++ b/ext/standard/tests/serialize/sleep_mangled_name_clash.phpt @@ -12,5 +12,7 @@ $s = serialize(new Test); var_dump(str_replace("\0", '\0', $s)); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: serialize(): "priv" is returned from __sleep() multiple times in %s on line %d string(37) "O:4:"Test":1:{s:10:"\0Test\0priv";N;}" diff --git a/ext/standard/tests/serialize/sleep_undefined_declared_properties.phpt b/ext/standard/tests/serialize/sleep_undefined_declared_properties.phpt index 3c7f802e670b6..c660b051b7830 100644 --- a/ext/standard/tests/serialize/sleep_undefined_declared_properties.phpt +++ b/ext/standard/tests/serialize/sleep_undefined_declared_properties.phpt @@ -21,6 +21,8 @@ var_dump(serialize(new Test)); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: serialize(): "pub" returned as member variable from __sleep() but does not exist in %s on line %d Warning: serialize(): "prot" returned as member variable from __sleep() but does not exist in %s on line %d diff --git a/ext/standard/tests/serialize/sleep_uninitialized_typed_prop.phpt b/ext/standard/tests/serialize/sleep_uninitialized_typed_prop.phpt index ebef92ca188ae..1c444a7dfda44 100644 --- a/ext/standard/tests/serialize/sleep_uninitialized_typed_prop.phpt +++ b/ext/standard/tests/serialize/sleep_uninitialized_typed_prop.phpt @@ -32,7 +32,8 @@ var_dump(unserialize(serialize($t)) == $t); var_dump($t); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d string(15) "O:4:"Test":0:{}" bool(true) bool(true) diff --git a/ext/standard/tests/serialize/unserialize_mem_leak.phpt b/ext/standard/tests/serialize/unserialize_mem_leak.phpt index 3ddb74a273df5..bad689c3705ad 100644 --- a/ext/standard/tests/serialize/unserialize_mem_leak.phpt +++ b/ext/standard/tests/serialize/unserialize_mem_leak.phpt @@ -1,7 +1,5 @@ --TEST-- Memleaks if unserialize return a self-referenced array/object ---INI-- -report_memleaks=1 --FILE-- getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ErrorException: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) diff --git a/ext/standard/tests/serialize/wakeup_deprecation_promoted_exception2.inc b/ext/standard/tests/serialize/wakeup_deprecation_promoted_exception2.inc new file mode 100644 index 0000000000000..b4f8b7e42940c --- /dev/null +++ b/ext/standard/tests/serialize/wakeup_deprecation_promoted_exception2.inc @@ -0,0 +1,7 @@ +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ErrorException: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) + diff --git a/ext/standard/tests/streams/bug69521.phpt b/ext/standard/tests/streams/bug69521.phpt index 9ec244f79963e..d335a68736eb4 100644 --- a/ext/standard/tests/streams/bug69521.phpt +++ b/ext/standard/tests/streams/bug69521.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #69521 Segfault in gc_collect_cycles() +Bug #69521 (Segfault in gc_collect_cycles()) --FILE-- getMessage(), "\n"; +} +fflush($readStream); +try { + fclose($readStream); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECTF-- +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d + +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d + +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d + +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d + +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d + +Warning: stream_select(): Cannot represent a stream of type user-space as a select()able descriptor in %s on line %d + +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d + +Warning: stream_select(): Cannot represent a stream of type user-space as a select()able descriptor in %s on line %d +No stream arrays were passed +fclose(): Argument #1 ($stream) must be an open stream resource diff --git a/ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt b/ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt new file mode 100644 index 0000000000000..52f9263c99aaa --- /dev/null +++ b/ext/standard/tests/streams/ghsa-3cr5-j632-f35r.phpt @@ -0,0 +1,26 @@ +--TEST-- +GHSA-3cr5-j632-f35r: Null byte termination in stream_socket_client() +--FILE-- + +--EXPECTF-- + +Warning: stream_socket_client(): Unable to connect to tcp://localhost\0.example.com:%d (The hostname must not contain null bytes) in %s +bool(false) diff --git a/ext/standard/tests/streams/stream_context_get_params_001.phpt b/ext/standard/tests/streams/stream_context_get_params_001.phpt index e8b107ccfe953..aaed575314e5b 100644 --- a/ext/standard/tests/streams/stream_context_get_params_001.phpt +++ b/ext/standard/tests/streams/stream_context_get_params_001.phpt @@ -4,16 +4,19 @@ stream_context_get_params() "stream_notification_callback"))); var_dump(stream_context_get_params($ctx)); -var_dump(stream_context_set_params($ctx, array("notification" => array("stream","notification_callback")))); +class MyStream { + public static function notification_callback() {} +} +var_dump(stream_context_set_params($ctx, array("notification" => ["MyStream", "notification_callback"]))); var_dump(stream_context_get_params($ctx)); var_dump(stream_context_get_params($ctx)); @@ -22,8 +25,7 @@ var_dump(stream_context_get_params($ctx)); var_dump(stream_context_get_options($ctx)); ?> ---EXPECTF-- -resource(%d) of type (stream-context) +--EXPECT-- array(1) { ["options"]=> array(0) { @@ -58,7 +60,7 @@ array(2) { ["notification"]=> array(2) { [0]=> - string(6) "stream" + string(8) "MyStream" [1]=> string(21) "notification_callback" } @@ -75,7 +77,7 @@ array(2) { ["notification"]=> array(2) { [0]=> - string(6) "stream" + string(8) "MyStream" [1]=> string(21) "notification_callback" } @@ -99,7 +101,7 @@ array(2) { ["notification"]=> array(2) { [0]=> - string(6) "stream" + string(8) "MyStream" [1]=> string(21) "notification_callback" } diff --git a/ext/standard/tests/streams/stream_context_set_params_notification_error.phpt b/ext/standard/tests/streams/stream_context_set_params_notification_error.phpt new file mode 100644 index 0000000000000..32af36d0d4777 --- /dev/null +++ b/ext/standard/tests/streams/stream_context_set_params_notification_error.phpt @@ -0,0 +1,21 @@ +--TEST-- +stream_context_set_params() with invalid notification option +--FILE-- + "fn_not_exist"])); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump(stream_context_set_params($ctx, ["notification" => ["myclass", "fn_not_exist"]])); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: stream_context_set_params(): Argument #1 ($context) must be an array with valid callbacks as values, function "fn_not_exist" not found or invalid function name +TypeError: stream_context_set_params(): Argument #1 ($context) must be an array with valid callbacks as values, class "myclass" not found diff --git a/ext/standard/tests/streams/stream_context_set_params_notification_valid_then_invalid.phpt b/ext/standard/tests/streams/stream_context_set_params_notification_valid_then_invalid.phpt new file mode 100644 index 0000000000000..9f654d61761e0 --- /dev/null +++ b/ext/standard/tests/streams/stream_context_set_params_notification_valid_then_invalid.phpt @@ -0,0 +1,20 @@ +--TEST-- +stream_context_set_params() with valid, then invalid notification option +--FILE-- + "foo"])); + +try { + var_dump(stream_context_set_params($ctx, ["notification" => "fn_not_exist"])); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +bool(true) +TypeError: stream_context_set_params(): Argument #1 ($context) must be an array with valid callbacks as values, function "fn_not_exist" not found or invalid function name diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt index cd1ba6b41dd80..1ac08dd5c841d 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt @@ -18,7 +18,7 @@ $socket = stream_socket_accept($server); var_dump(stream_get_meta_data($client)); echo "\n\nSet a timeout on the client and attempt a read:\n"; -socket_set_timeout($client, 0, 1000); +stream_set_timeout($client, 0, 1000); fread($client, 1); var_dump(stream_get_meta_data($client)); diff --git a/ext/standard/tests/streams/user-stream-dir-open-bailout.phpt b/ext/standard/tests/streams/user-stream-dir-open-bailout.phpt new file mode 100644 index 0000000000000..d7421ee9dea82 --- /dev/null +++ b/ext/standard/tests/streams/user-stream-dir-open-bailout.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bailout (E_ERROR) during UserStream Dir Open +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTF-- +Fatal error: Bailout in %s on line %d diff --git a/ext/standard/tests/streams/user-stream-error.phpt b/ext/standard/tests/streams/user-stream-error.phpt deleted file mode 100644 index 8ad4be644181f..0000000000000 --- a/ext/standard/tests/streams/user-stream-error.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -E_ERROR during UserStream Open ---FILE-- - ---EXPECTF-- -Fatal error: Uncaught Error: Call to undefined function _some_undefined_function() in %s%euser-stream-error.php:%d -Stack trace: -#0 [internal function]: FailStream->stream_open('mystream://foo', 'r', 0, NULL) -#1 %s%euser-stream-error.php(%d): fopen('mystream://foo', 'r') -#2 {main} - thrown in %s%euser-stream-error.php on line %d diff --git a/ext/standard/tests/streams/user-stream-open-bailout.phpt b/ext/standard/tests/streams/user-stream-open-bailout.phpt new file mode 100644 index 0000000000000..552e32a04a237 --- /dev/null +++ b/ext/standard/tests/streams/user-stream-open-bailout.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bailout (E_ERROR) during UserStream Open +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTF-- +Fatal error: Bailout in %s on line %d diff --git a/ext/standard/tests/strings/bug72663_3.phpt b/ext/standard/tests/strings/bug72663_3.phpt index bcec2b182a1da..d4f157cb7877e 100644 --- a/ext/standard/tests/strings/bug72663_3.phpt +++ b/ext/standard/tests/strings/bug72663_3.phpt @@ -14,5 +14,7 @@ unserialize($poc); ?> DONE --EXPECTF-- +Deprecated: The __wakeup() serialization magic method has been deprecated. Implement __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: unserialize(): Error at offset 50 of 50 bytes in %s on line %d DONE diff --git a/ext/standard/tests/strings/chr_out_of_range.phpt b/ext/standard/tests/strings/chr_out_of_range.phpt new file mode 100644 index 0000000000000..8381850e80654 --- /dev/null +++ b/ext/standard/tests/strings/chr_out_of_range.phpt @@ -0,0 +1,15 @@ +--TEST-- +chr() with out of range values +--FILE-- + +--EXPECTF-- +Deprecated: chr(): Providing a value not in-between 0 and 255 is deprecated, this is because a byte value must be in the [0, 255] interval. The value used will be constrained using % 256 in %s on line 3 +bool(true) + +Deprecated: chr(): Providing a value not in-between 0 and 255 is deprecated, this is because a byte value must be in the [0, 255] interval. The value used will be constrained using % 256 in %s on line 4 +bool(true) diff --git a/ext/standard/tests/strings/chr_variation1.phpt b/ext/standard/tests/strings/chr_variation1.phpt index f045fdb54a005..d181e752c2aad 100644 --- a/ext/standard/tests/strings/chr_variation1.phpt +++ b/ext/standard/tests/strings/chr_variation1.phpt @@ -5,36 +5,17 @@ Test chr() function : usage variations - test values for $ascii argument echo "*** Testing chr() function: with unexpected inputs for 'ascii' argument ***\n"; -//defining a class -class sample { - public function __toString() { - return "sample object"; - } -} - -//getting the resource -$file_handle = fopen(__FILE__, "r"); - // array with different values for $input -$inputs = array ( - - // integer values -/*1*/ 0, - 1, - 255, - 256, - - // float values -/*5*/ 10.5, - -20.5, - 1.1234e6, - - // boolean values -/*11*/ true, - false, - TRUE, - FALSE, -); +$inputs = [ + 0, + 1, + 255, + // float values + 10.5, + // bool values + true, + false, +]; // loop through with each element of the $inputs array to test chr() function $count = 1; @@ -44,8 +25,6 @@ foreach($inputs as $input) { $count ++; } -fclose($file_handle); //closing the file handle - ?> --EXPECTF-- *** Testing chr() function: with unexpected inputs for 'ascii' argument *** @@ -56,22 +35,10 @@ string(2) "01" -- Iteration 3 -- string(2) "ff" -- Iteration 4 -- -string(2) "00" --- Iteration 5 -- Deprecated: Implicit conversion from float 10.5 to int loses precision in %s on line %d string(2) "0a" --- Iteration 6 -- - -Deprecated: Implicit conversion from float -20.5 to int loses precision in %s on line %d -string(2) "ec" --- Iteration 7 -- -string(2) "48" --- Iteration 8 -- -string(2) "01" --- Iteration 9 -- -string(2) "00" --- Iteration 10 -- +-- Iteration 5 -- string(2) "01" --- Iteration 11 -- +-- Iteration 6 -- string(2) "00" diff --git a/ext/standard/tests/strings/get_html_translation_table_basic6.phpt b/ext/standard/tests/strings/get_html_translation_table_basic6.phpt index 1715b0852bfac..f4fadf7134c30 100644 --- a/ext/standard/tests/strings/get_html_translation_table_basic6.phpt +++ b/ext/standard/tests/strings/get_html_translation_table_basic6.phpt @@ -3,7 +3,7 @@ Test get_html_translation_table() function : basic functionality - HTML 5/Window --FILE-- getMessage(), "\n"; } ?> ---EXPECTF-- -Deprecated: setlocale(): Passing null to parameter #2 ($locales) of type string is deprecated in %s on line %d +--EXPECT-- no diff --git a/ext/standard/tests/strings/gh18976.phpt b/ext/standard/tests/strings/gh18976.phpt new file mode 100644 index 0000000000000..aa58167f9d45b --- /dev/null +++ b/ext/standard/tests/strings/gh18976.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-18976 (pack overflow with h/H format) +--INI-- +memory_limit=-1 +--FILE-- + +--EXPECTF-- + +Warning: pack(): Type h: not enough characters in string in %s on line %d + +Warning: pack(): Type H: not enough characters in string in %s on line %d diff --git a/ext/standard/tests/strings/gh19070.phpt b/ext/standard/tests/strings/gh19070.phpt new file mode 100644 index 0000000000000..e44696443cc97 --- /dev/null +++ b/ext/standard/tests/strings/gh19070.phpt @@ -0,0 +1,8 @@ +--TEST-- +GH-19070 (setlocale($type, NULL) should not be deprecated) +--FILE-- + +--EXPECTF-- +string(%d) "%s" diff --git a/ext/standard/tests/strings/htmlentities06.phpt b/ext/standard/tests/strings/htmlentities06.phpt index c046c798d9a71..4066b6c2e6804 100644 --- a/ext/standard/tests/strings/htmlentities06.phpt +++ b/ext/standard/tests/strings/htmlentities06.phpt @@ -7,7 +7,6 @@ internal_encoding=ISO-8859-15 mbstring --FILE-- diff --git a/ext/standard/tests/strings/htmlentities07.phpt b/ext/standard/tests/strings/htmlentities07.phpt index 421a1c7c7abed..7e735a434ab80 100644 --- a/ext/standard/tests/strings/htmlentities07.phpt +++ b/ext/standard/tests/strings/htmlentities07.phpt @@ -7,7 +7,6 @@ internal_encoding=ISO-8859-1 mbstring --FILE-- diff --git a/ext/standard/tests/strings/htmlentities08.phpt b/ext/standard/tests/strings/htmlentities08.phpt index 38d1d1008cade..3b177a4b99452 100644 --- a/ext/standard/tests/strings/htmlentities08.phpt +++ b/ext/standard/tests/strings/htmlentities08.phpt @@ -7,7 +7,6 @@ internal_encoding=EUC-JP mbstring --FILE-- diff --git a/ext/standard/tests/strings/htmlentities09.phpt b/ext/standard/tests/strings/htmlentities09.phpt index bdd5aa39e4aaa..891cababb55a5 100644 --- a/ext/standard/tests/strings/htmlentities09.phpt +++ b/ext/standard/tests/strings/htmlentities09.phpt @@ -7,7 +7,6 @@ internal_encoding=Shift_JIS mbstring --FILE-- diff --git a/ext/standard/tests/strings/ord_basic.phpt b/ext/standard/tests/strings/ord_basic.phpt index 0921dfda55aa2..4e00bd0b22f5e 100644 --- a/ext/standard/tests/strings/ord_basic.phpt +++ b/ext/standard/tests/strings/ord_basic.phpt @@ -15,7 +15,6 @@ var_dump(ord("@")); var_dump(ord("\n")); var_dump(ord("\x0A")); var_dump(ord("\xFF")); -var_dump(ord("Hello")); // Make sure all valid ascii chars round trip for ($i = 0; $i < 255; $i++) { @@ -37,4 +36,3 @@ int(64) int(10) int(10) int(255) -int(72) diff --git a/ext/standard/tests/strings/ord_not_1_byte.phpt b/ext/standard/tests/strings/ord_not_1_byte.phpt new file mode 100644 index 0000000000000..ba019cf3dd4a6 --- /dev/null +++ b/ext/standard/tests/strings/ord_not_1_byte.phpt @@ -0,0 +1,15 @@ +--TEST-- +ord() with values not one byte long +--FILE-- + +--EXPECTF-- +Deprecated: ord(): Providing an empty string is deprecated in %s on line 3 +int(0) + +Deprecated: ord(): Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead in %s on line 4 +int(72) diff --git a/ext/standard/tests/strings/str_increment_polyfill.phpt b/ext/standard/tests/strings/str_increment_polyfill.phpt index 36ad262598f4e..1f9f948aa200b 100644 --- a/ext/standard/tests/strings/str_increment_polyfill.phpt +++ b/ext/standard/tests/strings/str_increment_polyfill.phpt @@ -10,9 +10,9 @@ function polyfill(string $s): string { /* Using increment operator would cast the string to float * Therefore we manually increment it to convert it to an "f"/"F" that doesn't get affected */ $c = $s[$offset]; - $c++; + @$c++; $s[$offset] = $c; - $s++; + @$s++; $s[$offset] = match ($s[$offset]) { 'f' => 'e', 'F' => 'E', @@ -22,7 +22,7 @@ function polyfill(string $s): string { return $s; } } - return ++$s; + return @++$s; } $strictlyAlphaNumeric = [ diff --git a/ext/standard/tests/strings/str_replace_variation2.phpt b/ext/standard/tests/strings/str_replace_variation2.phpt index 957c990555ea5..d8dcd58e1b604 100644 --- a/ext/standard/tests/strings/str_replace_variation2.phpt +++ b/ext/standard/tests/strings/str_replace_variation2.phpt @@ -12,7 +12,7 @@ precision=14 echo "\n*** Testing str_replace() with various subjects ***"; $subject = "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE\000 \x000\x5ACD\0abcd \xXYZ\tabcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)"; + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)"; /* needles in an array to be compared in the string $string */ $search_str = array ( @@ -48,7 +48,7 @@ $search_str = array ( 'b', '\t', "\t", - chr(128).chr(234).chr(65).chr(255).chr(256), + chr(128).chr(234).chr(65).chr(255).chr(0), $subject ); @@ -65,233 +65,233 @@ for( $i = 0; $i < count($search_str); $i++ ) { *** Testing str_replace() with various subjects *** --- Iteration 0 --- -- String after replacing the search value is => -- -string(181) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(179) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!FOUND - ?FOUND chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?FOUND chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '2' times --- Iteration 1 --- -- String after replacing the search value is => -- -string(181) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(179) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!FOUND - ?FOUND chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?FOUND chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '2' times --- Iteration 2 --- -- String after replacing the search value is => -- -string(186) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(184) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: FOUND - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 3 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 4 --- -- String after replacing the search value is => -- -string(186) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(184) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $FOUND: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 5 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 6 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 7 --- -- String after replacing the search value is => -- -string(193) "Hello, world,0120333.3445FOUND67 NULL TRUE FALSE%0 +string(191) "Hello, world,0120333.3445FOUND67 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 8 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 9 --- -- String after replacing the search value is => -- -string(197) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0FOUND \xXYZ FOUND $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '2' times --- Iteration 10 --- -- String after replacing the search value is => -- -string(197) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xFOUND abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 11 --- -- String after replacing the search value is => -- -string(196) "Hello, world,0120333.3445-1.234567 FOUND TRUE FALSE%0 +string(194) "Hello, world,0120333.3445-1.234567 FOUND TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 12 --- -- String after replacing the search value is => -- -string(211) "Hello, world,FOUND12FOUND333.3445-1.234567 NULL TRUE FALSE%0 +string(213) "Hello, world,FOUND12FOUND333.3445-1.234567 NULL TRUE FALSE%0 %0FOUNDZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(FOUND).chr(128).chr(234).chr(65).chr(255).chr(256)" --- search string has found '4' times + ?Hello, World chr(FOUND).chr(128).chr(234).chr(65).chr(255).chr(FOUND)" +-- search string has found '5' times --- Iteration 13 --- -- String after replacing the search value is => -- -string(211) "Hello, world,FOUND12FOUND333.3445-1.234567 NULL TRUE FALSE%0 +string(213) "Hello, world,FOUND12FOUND333.3445-1.234567 NULL TRUE FALSE%0 %0FOUNDZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(FOUND).chr(128).chr(234).chr(65).chr(255).chr(256)" --- search string has found '4' times + ?Hello, World chr(FOUND).chr(128).chr(234).chr(65).chr(255).chr(FOUND)" +-- search string has found '5' times --- Iteration 14 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 15 --- -- String after replacing the search value is => -- -string(335) "Hello,FOUNDworld,0120333.3445-1.234567FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDNULLFOUNDTRUEFOUNDFALSE%0 +string(333) "Hello,FOUNDworld,0120333.3445-1.234567FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDNULLFOUNDTRUEFOUNDFALSE%0 FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUND%00ZCD%0abcdFOUND\xXYZ abcdFOUND$$@#%^&*!~,.:;?:FOUND!!Hello,FOUNDWorld -FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUND?Hello,FOUNDWorldFOUNDchr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" +FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUND?Hello,FOUNDWorldFOUNDchr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '35' times --- Iteration 16 --- -- String after replacing the search value is => -- -string(207) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSEFOUND +string(205) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSEFOUND FOUND0ZCDFOUNDabcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '3' times --- Iteration 17 --- -- String after replacing the search value is => -- -string(198) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(196) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 FOUNDZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 18 --- -- String after replacing the search value is => -- -string(198) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(196) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00FOUNDD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 19 --- -- String after replacing the search value is => -- -string(198) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(196) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 FOUNDZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 20 --- -- String after replacing the search value is => -- -string(198) "Hello, world,0120333FOUND445-1.234567 NULL TRUE FALSE%0 +string(196) "Hello, world,0120333FOUND445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 21 --- -- String after replacing the search value is => -- -string(207) "Hello, world,0FOUND20333.3445-FOUND.234567 NULL TRUE FALSE%0 +string(205) "Hello, world,0FOUND20333.3445-FOUND.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(FOUND28).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(FOUND28).chr(234).chr(65).chr(255).chr(0)" -- search string has found '3' times --- Iteration 22 --- -- String after replacing the search value is => -- -string(196) "Hello, world,0120333.3445-1.234567 NULL FOUND FALSE%0 +string(194) "Hello, world,0120333.3445-1.234567 NULL FOUND FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 23 --- -- String after replacing the search value is => -- -string(207) "Hello, world,0FOUND20333.3445-FOUND.234567 NULL TRUE FALSE%0 +string(205) "Hello, world,0FOUND20333.3445-FOUND.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(FOUND28).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(FOUND28).chr(234).chr(65).chr(255).chr(0)" -- search string has found '3' times --- Iteration 24 --- -- String after replacing the search value is => -- -string(207) "Hello, world,0FOUND20333.3445-FOUND.234567 NULL TRUE FALSE%0 +string(205) "Hello, world,0FOUND20333.3445-FOUND.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(FOUND28).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(FOUND28).chr(234).chr(65).chr(255).chr(0)" -- search string has found '3' times --- Iteration 25 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 26 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FOUND%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FOUND%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 27 --- -- String after replacing the search value is => -- -string(335) "Hello,FOUNDworld,0120333.3445-1.234567FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDNULLFOUNDTRUEFOUNDFALSE%0 +string(333) "Hello,FOUNDworld,0120333.3445-1.234567FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDNULLFOUNDTRUEFOUNDFALSE%0 FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUND%00ZCD%0abcdFOUND\xXYZ abcdFOUND$$@#%^&*!~,.:;?:FOUND!!Hello,FOUNDWorld -FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUND?Hello,FOUNDWorldFOUNDchr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" +FOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUNDFOUND?Hello,FOUNDWorldFOUNDchr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '35' times --- Iteration 28 --- -- String after replacing the search value is => -- -string(190) "Hello, world,0120333.3445-1.234567FOUNDNULL TRUE FALSE%0 +string(188) "Hello, world,0120333.3445-1.234567FOUNDNULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 29 --- -- String after replacing the search value is => -- -string(203) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(201) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0aFOUNDcd \xXYZ aFOUNDcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '2' times --- Iteration 30 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 31 --- -- String after replacing the search value is => -- -string(199) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(197) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZFOUNDabcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '1' times --- Iteration 32 --- -- String after replacing the search value is => -- -string(195) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 +string(193) "Hello, world,0120333.3445-1.234567 NULL TRUE FALSE%0 %00ZCD%0abcd \xXYZ abcd $$@#%^&*!~,.:;?: !!Hello, World - ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(256)" + ?Hello, World chr(0).chr(128).chr(234).chr(65).chr(255).chr(0)" -- search string has found '0' times --- Iteration 33 --- diff --git a/ext/standard/tests/strings/strcasecmp.phpt b/ext/standard/tests/strings/strcasecmp.phpt index e55b2a684fb21..1136774b38acc 100644 --- a/ext/standard/tests/strings/strcasecmp.phpt +++ b/ext/standard/tests/strings/strcasecmp.phpt @@ -9,7 +9,7 @@ precision = 12 echo "#### Basic and Possible operations ####"; /* creating an array of strings to be compared */ $arrays = array( - array("a", 'A', chr(128), chr(255), chr(256)), + array("a", 'A', chr(128), chr(255), chr(0)), array("acc", "Acc", 'aC', "acCc", 'acd', "?acc", 'Acc!', "$!acc", ";acc"), array("1", "0", 0, "-1", -1, "", TRUE, true, FALSE, "string"), array(10.5, 1.5, 9.5, 11.5, 100.5, 10.5E1, -10.5, 10, 0.5) diff --git a/ext/standard/tests/strings/strcmp.phpt b/ext/standard/tests/strings/strcmp.phpt index 5310566d53b60..fa94a9cc3a01a 100644 --- a/ext/standard/tests/strings/strcmp.phpt +++ b/ext/standard/tests/strings/strcmp.phpt @@ -9,7 +9,7 @@ precision = 12 echo "#### Basic and Possible operations ####"; /* creating an array of strings to be compared */ $arrays = array( - array("a", "A", 'a', 'A', chr(128), chr(255), chr(256)), + array("a", "A", 'a', 'A', chr(128), chr(255), chr(0)), array("acc", "Acc", 'ac', "accc", 'acd', "?acc", 'acc!', "$!acc", ";acc"), array("1", "0", 0, "-1", -1, "", TRUE, FALSE, "string"), array(10.5, 1.5, 9.5, 11.5, 100.5, 10.5E1, -10.5, 10, 0.5) diff --git a/ext/standard/tests/strings/strlen.phpt b/ext/standard/tests/strings/strlen.phpt index b98111f15e672..b1ff4f4e74d97 100644 --- a/ext/standard/tests/strings/strlen.phpt +++ b/ext/standard/tests/strings/strlen.phpt @@ -24,8 +24,8 @@ $strings = array( "Hello, World", "\0000", // len = 2 "0", 0, - "\t", // len = 1 - '\t', // len = 2 + "\t", // len = 1 + '\t', // len = 2 TRUE, FALSE, "Hello, World\0", @@ -36,7 +36,7 @@ $strings = array( "Hello, World", "Hello, World\t", "Hello, World\\", " ", - chr(128).chr(234).chr(65).chr(255).chr(256), + chr(128).chr(234).chr(65).chr(255).chr(0), "abcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+=|?><-;:$ []{}{{{}}}[[[[]][]]]***&&&^^%$###@@!!@#$%&^&**/////|\\\\\\ @@ -113,11 +113,11 @@ var_dump(strlen("{$str}S")); echo "\n--- strlen for long float values ---\n"; /* Here two different outputs, which depends on the rounding value before converting to string. Here Precision = 12 */ -var_dump(strlen(10.55555555555555555555555555)); // len = 13 -var_dump(strlen(10.55555555595555555555555555)); // len = 12 +var_dump(strlen(10.55555555555555555555555555)); // len = 13 +var_dump(strlen(10.55555555595555555555555555)); // len = 12 echo "\n--- Nested strlen() ---\n"; -var_dump(strlen(strlen("Hello"))); // len=1 +var_dump(strlen(strlen("Hello"))); // len=1 echo "Done\n"; ?> diff --git a/ext/standard/tests/strings/strncasecmp_variation6.phpt b/ext/standard/tests/strings/strncasecmp_variation6.phpt index 78a0ddd549bf2..3a7b90616a2d2 100644 --- a/ext/standard/tests/strings/strncasecmp_variation6.phpt +++ b/ext/standard/tests/strings/strncasecmp_variation6.phpt @@ -10,7 +10,7 @@ echo "*** Test strncasecmp() function: with binary inputs ***\n"; echo "\n-- Checking with all 256 characters given, in binary format --\n"; /* loop through to get all 256 character's equivalent binary value, and check working of strncasecmp() */ $count = 1; -for($ASCII = 0; $ASCII <= 255; $ASCII++) { +for($ASCII = 0; $ASCII < 255; $ASCII++) { $str1 = decbin($ASCII); //ASCII value in binary form $str2 = decbin( ord( chr($ASCII) ) ); //Getting equivalent ASCII value for the character in binary form echo "-- Iteration $count --\n"; @@ -21,7 +21,7 @@ for($ASCII = 0; $ASCII <= 255; $ASCII++) { echo "\n-- Checking with out of character's range, given in binary format --\n"; $str1 = decbin(256); -$str2 = decbin( ord( chr(256) )); +$str2 = decbin( ord( chr(0) )); var_dump( strncasecmp($str1, $str2, 8) ); //comparing all the 8-bits; expected: int(1) echo "\n*** Done ***\n"; @@ -795,9 +795,6 @@ int(0) -- Iteration 255 -- int(0) int(0) --- Iteration 256 -- -int(0) -int(0) -- Checking with out of character's range, given in binary format -- int(1) diff --git a/ext/standard/tests/strings/strpos_variation1.phpt b/ext/standard/tests/strings/strpos_variation1.phpt index f28517316dc46..d01b9eba24d7c 100644 --- a/ext/standard/tests/strings/strpos_variation1.phpt +++ b/ext/standard/tests/strings/strpos_variation1.phpt @@ -9,8 +9,8 @@ echo bin2hex( chr(128) ) ." => "; var_dump( strpos($string, chr(128)) ); echo bin2hex( chr(255) ) ." => "; var_dump( strpos($string, chr(255), 3) ); -echo bin2hex( chr(256) ) ." => "; -var_dump( strpos($string, chr(256)) ); +echo bin2hex( chr(0) ) ." => "; +var_dump( strpos($string, chr(0)) ); ?> DONE diff --git a/ext/standard/tests/strings/strstr_variation1.phpt b/ext/standard/tests/strings/strstr_variation1.phpt index aade1fd5f85d4..30699702f8899 100644 --- a/ext/standard/tests/strings/strstr_variation1.phpt +++ b/ext/standard/tests/strings/strstr_variation1.phpt @@ -9,8 +9,8 @@ echo bin2hex( chr(128) ) ." => "; var_dump( bin2hex( strstr($string, chr(128) ) ) ); echo bin2hex( chr(255) ) ." => "; var_dump( bin2hex( strstr($string, chr(255) ) ) ); -echo bin2hex( chr(256) ) ." => "; -var_dump( bin2hex( strstr($string, chr(256) ) ) ); +echo bin2hex( chr(0) ) ." => "; +var_dump( bin2hex( strstr($string, chr(0) ) ) ); ?> DONE diff --git a/ext/standard/tests/strings/substr_count_variation_001.phpt b/ext/standard/tests/strings/substr_count_variation_001.phpt index d76c56d60fb21..d7ac3dcd22d62 100644 --- a/ext/standard/tests/strings/substr_count_variation_001.phpt +++ b/ext/standard/tests/strings/substr_count_variation_001.phpt @@ -14,10 +14,10 @@ var_dump( substr_count("abcabcabcabcabc", "abca") ); var_dump( substr_count("abcabcabcabcabc", "abca", 2) ); echo "\n-- complex strings containing other than 7-bit chars --\n"; -$str = chr(128).chr(129).chr(128).chr(256).chr(255).chr(254).chr(255); +$str = chr(128).chr(129).chr(128).chr(0).chr(255).chr(254).chr(255); var_dump(substr_count($str, chr(128))); var_dump(substr_count($str, chr(255))); -var_dump(substr_count($str, chr(256))); +var_dump(substr_count($str, chr(0))); echo "\n-- heredoc string --\n"; $string = <<url_app.s) == 0) { + } else { url_adapt_state_ex_t *ctx = url_state; if (ctx->buf.s && ZSTR_LEN(ctx->buf.s)) { smart_str_append(&ctx->result, ctx->buf.s); @@ -715,8 +715,6 @@ static inline void php_url_scanner_session_handler_impl(char *output, size_t out } else { *handled_output = estrndup(output, *handled_output_len = output_len); } - } else { - *handled_output = NULL; } } diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index d91e168ce53a7..f6af1089b03ef 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -283,10 +283,6 @@ static php_stream_filter *user_filter_factory_create(const char *filtername, } filter = php_stream_filter_alloc(&userfilter_ops, NULL, 0); - if (filter == NULL) { - zval_ptr_dtor(&obj); - return NULL; - } /* filtername */ add_property_string(&obj, "filtername", (char*)filtername); diff --git a/ext/standard/var.c b/ext/standard/var.c index 1c2b0eb164a1c..9363065483d16 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -737,7 +737,10 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var, b return 0; } else if (!in_rcn_array && Z_REFCOUNT_P(var) == 1 - && (Z_OBJ_P(var)->properties == NULL || GC_REFCOUNT(Z_OBJ_P(var)->properties) == 1)) { + && (Z_OBJ_P(var)->properties == NULL || GC_REFCOUNT(Z_OBJ_P(var)->properties) == 1) + /* __serialize and __sleep may arbitrarily increase the refcount */ + && Z_OBJCE_P(var)->__serialize == NULL + && zend_hash_find_known_hash(&Z_OBJCE_P(var)->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP)) == NULL) { return 0; } @@ -998,18 +1001,11 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable /* we should still add element even if it's not OK, * since we already wrote the length of the array before */ if (Z_TYPE_P(data) == IS_ARRAY) { - if (UNEXPECTED(Z_IS_RECURSIVE_P(data)) - || UNEXPECTED(Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))) { + if (UNEXPECTED(Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))) { php_add_var_hash(var_hash, struc, in_rcn_array); smart_str_appendl(buf, "N;", 2); } else { - if (Z_REFCOUNTED_P(data)) { - Z_PROTECT_RECURSION_P(data); - } php_var_serialize_intern(buf, data, var_hash, in_rcn_array, false); - if (Z_REFCOUNTED_P(data)) { - Z_UNPROTECT_RECURSION_P(data); - } } } else { php_var_serialize_intern(buf, data, var_hash, in_rcn_array, false); diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index cbd457e16fdb1..353c7086d4304 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -1312,10 +1312,12 @@ object ":" uiv ":" ["] { YYCURSOR = *p; if (*(YYCURSOR) != ':') { + zend_string_release_ex(class_name, 0); return 0; } if (*(YYCURSOR+1) != '{') { *p = YYCURSOR+1; + zend_string_release_ex(class_name, 0); return 0; } diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c index 1f4cafd2bce0f..456a6f51735e0 100644 --- a/ext/sysvmsg/sysvmsg.c +++ b/ext/sysvmsg/sysvmsg.c @@ -127,32 +127,32 @@ PHP_MINFO_FUNCTION(sysvmsg) /* {{{ Set information for a message queue */ PHP_FUNCTION(msg_set_queue) { - zval *queue, *data; + zval *queue; + HashTable *data; sysvmsg_queue_t *mq = NULL; struct msqid_ds stat; - RETVAL_FALSE; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oa", &queue, sysvmsg_queue_ce, &data) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oh", &queue, sysvmsg_queue_ce, &data) == FAILURE) { RETURN_THROWS(); } mq = Z_SYSVMSG_QUEUE_P(queue); + RETVAL_FALSE; if (msgctl(mq->id, IPC_STAT, &stat) == 0) { zval *item; /* now pull out members of data and set them in the stat buffer */ - if ((item = zend_hash_str_find(Z_ARRVAL_P(data), "msg_perm.uid", sizeof("msg_perm.uid") - 1)) != NULL) { + if ((item = zend_hash_str_find(data, ZEND_STRL("msg_perm.uid"))) != NULL) { stat.msg_perm.uid = zval_get_long(item); } - if ((item = zend_hash_str_find(Z_ARRVAL_P(data), "msg_perm.gid", sizeof("msg_perm.gid") - 1)) != NULL) { + if ((item = zend_hash_str_find(data, ZEND_STRL("msg_perm.gid"))) != NULL) { stat.msg_perm.gid = zval_get_long(item); } - if ((item = zend_hash_str_find(Z_ARRVAL_P(data), "msg_perm.mode", sizeof("msg_perm.mode") - 1)) != NULL) { + if ((item = zend_hash_str_find(data, ZEND_STRL("msg_perm.mode"))) != NULL) { stat.msg_perm.mode = zval_get_long(item); } - if ((item = zend_hash_str_find(Z_ARRVAL_P(data), "msg_qbytes", sizeof("msg_qbytes") - 1)) != NULL) { + if ((item = zend_hash_str_find(data, ZEND_STRL("msg_qbytes"))) != NULL) { stat.msg_qbytes = zval_get_long(item); } if (msgctl(mq->id, IPC_SET, &stat) == 0) { @@ -169,28 +169,27 @@ PHP_FUNCTION(msg_stat_queue) sysvmsg_queue_t *mq = NULL; struct msqid_ds stat; - RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &queue, sysvmsg_queue_ce) == FAILURE) { RETURN_THROWS(); } mq = Z_SYSVMSG_QUEUE_P(queue); - if (msgctl(mq->id, IPC_STAT, &stat) == 0) { - array_init(return_value); - - add_assoc_long(return_value, "msg_perm.uid", stat.msg_perm.uid); - add_assoc_long(return_value, "msg_perm.gid", stat.msg_perm.gid); - add_assoc_long(return_value, "msg_perm.mode", stat.msg_perm.mode); - add_assoc_long(return_value, "msg_stime", stat.msg_stime); - add_assoc_long(return_value, "msg_rtime", stat.msg_rtime); - add_assoc_long(return_value, "msg_ctime", stat.msg_ctime); - add_assoc_long(return_value, "msg_qnum", stat.msg_qnum); - add_assoc_long(return_value, "msg_qbytes", stat.msg_qbytes); - add_assoc_long(return_value, "msg_lspid", stat.msg_lspid); - add_assoc_long(return_value, "msg_lrpid", stat.msg_lrpid); + if (msgctl(mq->id, IPC_STAT, &stat) != 0) { + RETURN_FALSE; } + + array_init_size(return_value, 10); + add_assoc_long(return_value, "msg_perm.uid", stat.msg_perm.uid); + add_assoc_long(return_value, "msg_perm.gid", stat.msg_perm.gid); + add_assoc_long(return_value, "msg_perm.mode", stat.msg_perm.mode); + add_assoc_long(return_value, "msg_stime", stat.msg_stime); + add_assoc_long(return_value, "msg_rtime", stat.msg_rtime); + add_assoc_long(return_value, "msg_ctime", stat.msg_ctime); + add_assoc_long(return_value, "msg_qnum", stat.msg_qnum); + add_assoc_long(return_value, "msg_qbytes", stat.msg_qbytes); + add_assoc_long(return_value, "msg_lspid", stat.msg_lspid); + add_assoc_long(return_value, "msg_lrpid", stat.msg_lrpid); } /* }}} */ @@ -203,11 +202,7 @@ PHP_FUNCTION(msg_queue_exists) RETURN_THROWS(); } - if (msgget(key, 0) < 0) { - RETURN_FALSE; - } - - RETURN_TRUE; + RETURN_BOOL(msgget(key, 0) >= 0); } /* }}} */ @@ -251,11 +246,7 @@ PHP_FUNCTION(msg_remove_queue) mq = Z_SYSVMSG_QUEUE_P(queue); - if (msgctl(mq->id, IPC_RMID, NULL) == 0) { - RETVAL_TRUE; - } else { - RETVAL_FALSE; - } + RETURN_BOOL(msgctl(mq->id, IPC_RMID, NULL) == 0); } /* }}} */ @@ -270,8 +261,6 @@ PHP_FUNCTION(msg_receive) struct php_msgbuf *messagebuffer = NULL; /* buffer to transmit */ int result; - RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olzlz|blz", &queue, sysvmsg_queue_ce, &desiredmsgtype, &out_msgtype, &maxsize, &out_message, &do_unserialize, &flags, &zerrcode) == FAILURE) { @@ -337,6 +326,7 @@ PHP_FUNCTION(msg_receive) if (zerrcode) { ZEND_TRY_ASSIGN_REF_LONG(zerrcode, errno); } + RETVAL_FALSE; } efree(messagebuffer); } @@ -353,8 +343,6 @@ PHP_FUNCTION(msg_send) int result; size_t message_len = 0; - RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz|bbz", &queue, sysvmsg_queue_ce, &msgtype, &message, &do_serialize, &blocking, &zerror) == FAILURE) { RETURN_THROWS(); @@ -395,10 +383,12 @@ PHP_FUNCTION(msg_send) message_len = spprintf(&p, 0, ZEND_LONG_FMT, Z_LVAL_P(message)); break; case IS_FALSE: - message_len = spprintf(&p, 0, "0"); + p = "0"; + message_len = 1; break; case IS_TRUE: - message_len = spprintf(&p, 0, "1"); + p = "1"; + message_len = 1; break; case IS_DOUBLE: message_len = spprintf(&p, 0, "%F", Z_DVAL_P(message)); @@ -412,7 +402,7 @@ PHP_FUNCTION(msg_send) messagebuffer = safe_emalloc(message_len, 1, sizeof(struct php_msgbuf)); memcpy(messagebuffer->mtext, p, message_len + 1); - if (Z_TYPE_P(message) != IS_STRING) { + if (Z_TYPE_P(message) == IS_LONG || Z_TYPE_P(message) == IS_DOUBLE) { efree(p); } } @@ -429,8 +419,9 @@ PHP_FUNCTION(msg_send) if (zerror) { ZEND_TRY_ASSIGN_REF_LONG(zerror, errno); } + RETURN_FALSE; } else { - RETVAL_TRUE; + RETURN_TRUE; } } /* }}} */ diff --git a/ext/sysvsem/sysvsem.c b/ext/sysvsem/sysvsem.c index 481d8ce28cc36..99ebda92273ef 100644 --- a/ext/sysvsem/sysvsem.c +++ b/ext/sysvsem/sysvsem.c @@ -266,7 +266,7 @@ PHP_FUNCTION(sem_get) /* }}} */ /* {{{ php_sysvsem_semop */ -static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire) +static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, bool acquire) { zval *arg_id; bool nowait = 0; @@ -311,14 +311,14 @@ static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire) /* {{{ Acquires the semaphore with the given id, blocking if necessary */ PHP_FUNCTION(sem_acquire) { - php_sysvsem_semop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); + php_sysvsem_semop(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } /* }}} */ /* {{{ Releases the semaphore with the given id */ PHP_FUNCTION(sem_release) { - php_sysvsem_semop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + php_sysvsem_semop(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); } /* }}} */ diff --git a/ext/sysvshm/php_sysvshm.h b/ext/sysvshm/php_sysvshm.h index e11caa6c61b3b..9576349e06d8e 100644 --- a/ext/sysvshm/php_sysvshm.h +++ b/ext/sysvshm/php_sysvshm.h @@ -41,17 +41,17 @@ typedef struct { typedef struct { zend_long key; - zend_long length; - zend_long next; + size_t length; + size_t next; char mem; } sysvshm_chunk; typedef struct { char magic[8]; - zend_long start; - zend_long end; - zend_long free; - zend_long total; + size_t start; + size_t end; + size_t free; + size_t total; } sysvshm_chunk_head; typedef struct { diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c index 332a8b47af1b6..c1372368a34b8 100644 --- a/ext/sysvshm/sysvshm.c +++ b/ext/sysvshm/sysvshm.c @@ -90,9 +90,9 @@ ZEND_GET_MODULE(sysvshm) /* TODO: Make this thread-safe. */ sysvshm_module php_sysvshm; -static int php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const char *data, zend_long len); -static zend_long php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key); -static int php_remove_shm_data(sysvshm_chunk_head *ptr, zend_long shm_varpos); +static bool php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const zend_string *data); +static ssize_t php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key); +static void php_remove_shm_data(sysvshm_chunk_head *ptr, size_t shm_varpos); /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(sysvshm) @@ -235,7 +235,6 @@ PHP_FUNCTION(shm_remove) PHP_FUNCTION(shm_put_var) { zval *shm_id, *arg_var; - int ret; zend_long shm_key; sysvshm_shm *shm_list_ptr; smart_str shm_var = {0}; @@ -262,13 +261,17 @@ PHP_FUNCTION(shm_put_var) RETURN_THROWS(); } + if (UNEXPECTED(shm_var.s == NULL)) { + RETURN_THROWS(); + } + /* insert serialized variable into shared memory */ - ret = php_put_shm_data(shm_list_ptr->ptr, shm_key, shm_var.s? ZSTR_VAL(shm_var.s) : NULL, shm_var.s? ZSTR_LEN(shm_var.s) : 0); + bool ret = php_put_shm_data(shm_list_ptr->ptr, shm_key, shm_var.s); /* free string */ smart_str_free(&shm_var); - if (ret == -1) { + if (!ret) { php_error_docref(NULL, E_WARNING, "Not enough shared memory left"); RETURN_FALSE; } @@ -283,7 +286,6 @@ PHP_FUNCTION(shm_get_var) zend_long shm_key; sysvshm_shm *shm_list_ptr; char *shm_data; - zend_long shm_varpos; sysvshm_chunk *shm_var; php_unserialize_data_t var_hash; @@ -299,9 +301,9 @@ PHP_FUNCTION(shm_get_var) /* setup string-variable and serialize */ /* get serialized variable from shared memory */ - shm_varpos = php_check_shm_data(shm_list_ptr->ptr, shm_key); + ssize_t shm_varpos = php_check_shm_data(shm_list_ptr->ptr, shm_key); - if (shm_varpos < 0) { + if (shm_varpos == -1) { php_error_docref(NULL, E_WARNING, "Variable key " ZEND_LONG_FMT " doesn't exist", shm_key); RETURN_FALSE; } @@ -342,7 +344,7 @@ PHP_FUNCTION(shm_has_var) PHP_FUNCTION(shm_remove_var) { zval *shm_id; - zend_long shm_key, shm_varpos; + zend_long shm_key; sysvshm_shm *shm_list_ptr; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &shm_id, sysvshm_ce, &shm_key)) { @@ -355,9 +357,9 @@ PHP_FUNCTION(shm_remove_var) RETURN_THROWS(); } - shm_varpos = php_check_shm_data(shm_list_ptr->ptr, shm_key); + ssize_t shm_varpos = php_check_shm_data(shm_list_ptr->ptr, shm_key); - if (shm_varpos < 0) { + if (shm_varpos == -1) { php_error_docref(NULL, E_WARNING, "Variable key " ZEND_LONG_FMT " doesn't exist", shm_key); RETURN_FALSE; } @@ -366,44 +368,41 @@ PHP_FUNCTION(shm_remove_var) } /* }}} */ -/* {{{ php_put_shm_data +/* {{{ * inserts an ascii-string into shared memory */ -static int php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const char *data, zend_long len) +static bool php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const zend_string *data) { sysvshm_chunk *shm_var; - zend_long total_size; - zend_long shm_varpos; + ssize_t shm_varpos; - total_size = ((zend_long) (len + sizeof(sysvshm_chunk) - 1) / sizeof(zend_long)) * sizeof(zend_long) + sizeof(zend_long); /* zend_long alligment */ + size_t total_size = ((zend_long) (ZSTR_LEN(data) + sizeof(sysvshm_chunk) - 1) / sizeof(zend_long)) * sizeof(zend_long) + sizeof(zend_long); /* zend_long alligment */ if ((shm_varpos = php_check_shm_data(ptr, key)) > 0) { php_remove_shm_data(ptr, shm_varpos); } if (ptr->free < total_size) { - return -1; /* not enough memory */ + return false; /* not enough memory */ } shm_var = (sysvshm_chunk *) ((char *) ptr + ptr->end); shm_var->key = key; - shm_var->length = len; + shm_var->length = ZSTR_LEN(data); shm_var->next = total_size; - memcpy(&(shm_var->mem), data, len); + memcpy(&(shm_var->mem), ZSTR_VAL(data), ZSTR_LEN(data)); ptr->end += total_size; ptr->free -= total_size; - return 0; + return true; } /* }}} */ -/* {{{ php_check_shm_data */ -static zend_long php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key) +static ssize_t php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key) { - zend_long pos; sysvshm_chunk *shm_var; ZEND_ASSERT(ptr); - pos = ptr->start; + size_t pos = ptr->start; for (;;) { if (pos >= ptr->end) { @@ -421,27 +420,22 @@ static zend_long php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key) } return -1; } -/* }}} */ -/* {{{ php_remove_shm_data */ -static int php_remove_shm_data(sysvshm_chunk_head *ptr, zend_long shm_varpos) +static void php_remove_shm_data(sysvshm_chunk_head *ptr, size_t shm_varpos) { sysvshm_chunk *chunk_ptr, *next_chunk_ptr; - zend_long memcpy_len; ZEND_ASSERT(ptr); chunk_ptr = (sysvshm_chunk *) ((char *) ptr + shm_varpos); next_chunk_ptr = (sysvshm_chunk *) ((char *) ptr + shm_varpos + chunk_ptr->next); - memcpy_len = ptr->end-shm_varpos - chunk_ptr->next; + size_t memcpy_len = ptr->end-shm_varpos - chunk_ptr->next; ptr->free += chunk_ptr->next; ptr->end -= chunk_ptr->next; if (memcpy_len > 0) { memmove(chunk_ptr, next_chunk_ptr, memcpy_len); } - return 0; } -/* }}} */ #endif /* HAVE_SYSVSHM */ diff --git a/ext/sysvshm/sysvshm.stub.php b/ext/sysvshm/sysvshm.stub.php index 4b6770063a31e..c89f67bc068ac 100644 --- a/ext/sysvshm/sysvshm.stub.php +++ b/ext/sysvshm/sysvshm.stub.php @@ -12,7 +12,7 @@ final class SysvSharedMemory function shm_attach(int $key, ?int $size = null, int $permissions = 0666): SysvSharedMemory|false {} -function shm_detach(SysvSharedMemory $shm): bool {} +function shm_detach(SysvSharedMemory $shm): true {} function shm_has_var(SysvSharedMemory $shm, int $key): bool {} diff --git a/ext/sysvshm/sysvshm_arginfo.h b/ext/sysvshm/sysvshm_arginfo.h index bca40b0e0944d..c3b803c37aea6 100644 --- a/ext/sysvshm/sysvshm_arginfo.h +++ b/ext/sysvshm/sysvshm_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 93677b78d9aaa4d6dbb5d1dcf3e79a8418add5c0 */ + * Stub hash: 792c695a705678a3779d62cef8a5136069f98dee */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_shm_attach, 0, 1, SysvSharedMemory, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) @@ -7,7 +7,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_shm_attach, 0, 1, SysvShared ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, permissions, IS_LONG, 0, "0666") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_detach, 0, 1, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_detach, 0, 1, IS_TRUE, 0) ZEND_ARG_OBJ_INFO(0, shm, SysvSharedMemory, 0) ZEND_END_ARG_INFO() @@ -16,7 +16,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_has_var, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) ZEND_END_ARG_INFO() -#define arginfo_shm_remove arginfo_shm_detach +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_remove, 0, 1, _IS_BOOL, 0) + ZEND_ARG_OBJ_INFO(0, shm, SysvSharedMemory, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shm_put_var, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, shm, SysvSharedMemory, 0) diff --git a/ext/sysvshm/tests/serialize_exception.phpt b/ext/sysvshm/tests/serialize_exception.phpt new file mode 100644 index 0000000000000..aae237e0fb38e --- /dev/null +++ b/ext/sysvshm/tests/serialize_exception.phpt @@ -0,0 +1,27 @@ +--TEST-- +__serialize() exception in shm_put_var() +--EXTENSIONS-- +sysvshm +--FILE-- +getMessage() . "\n"; +} + +shm_remove($s); + +?> +--EXPECT-- +no diff --git a/ext/tidy/config.m4 b/ext/tidy/config.m4 index bb85236346593..55474d7d951df 100644 --- a/ext/tidy/config.m4 +++ b/ext/tidy/config.m4 @@ -57,7 +57,9 @@ if test "$PHP_TIDY" != "no"; then [], [-L$TIDY_LIBDIR]) - PHP_CHECK_LIBRARY([$TIDY_LIB_NAME], [tidyOptGetCategory], + dnl The tidyOptGetCategory function (added in libtidy 5.4.0) if only useable + dnl if TidyInternalCategory (added in libtidy 5.6.0) is also present. + PHP_CHECK_LIBRARY([$TIDY_LIB_NAME], [tidyInternalCategory], [AC_DEFINE([HAVE_TIDYOPTGETCATEGORY], [1], [Define to 1 if Tidy library has the 'tidyOptGetCategory' function.])], [], diff --git a/ext/tidy/tests/025.phpt b/ext/tidy/tests/025.phpt index eda79a9885178..d641993491109 100644 --- a/ext/tidy/tests/025.phpt +++ b/ext/tidy/tests/025.phpt @@ -19,7 +19,7 @@ $n = $tidy->Root()->child[0]->child[1]->child[0]; var_dump($n->isComment()); var_dump((string)$n); var_dump((bool)$n); -var_dump((double)$n); +var_dump((float)$n); var_dump((int)$n); var_dump($tidy->Root()->child[0]->child[0]->hasSiblings()); diff --git a/ext/tidy/tests/031.phpt b/ext/tidy/tests/031.phpt index e41d94be2f794..3b0ac39b209e8 100644 --- a/ext/tidy/tests/031.phpt +++ b/ext/tidy/tests/031.phpt @@ -7,7 +7,7 @@ tidy --FILE-- '; -$config = array('doctype' => 'php'); +$config = array('doctype' => 'auto'); $tidy = tidy_parse_string($buffer, $config); var_dump(tidy_config_count($tidy)); diff --git a/ext/tidy/tests/tidy_error1.phpt b/ext/tidy/tests/tidy_error1.phpt index 0660f37437e2b..5e7593762a937 100644 --- a/ext/tidy/tests/tidy_error1.phpt +++ b/ext/tidy/tests/tidy_error1.phpt @@ -32,7 +32,15 @@ try { echo $e::class, ": ", $e->getMessage(), PHP_EOL; } -$config = ['doctype' => 'php', 0 => 'value2']; +$config = ['doctype' => 'php']; + +try { + var_dump($tidy->parseString($buffer, $config)); +} catch (\TypeError $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; +} + +$config = ['doctype' => 'auto', 0 => 'value2']; try { var_dump($tidy->parseString($buffer, $config)); @@ -45,4 +53,5 @@ try { ValueError: tidy::parseString(): Argument #2 ($config) Unknown Tidy configuration option "bogus" TypeError: tidy::parseString(): Argument #2 ($config) must be of type array with keys as string ValueError: tidy::parseString(): Argument #2 ($config) Attempting to set read-only option "doctype-mode" +TypeError: tidy::parseString(): Argument #2 ($config) option "doctype" does not accept "php" as a value TypeError: tidy::parseString(): Argument #2 ($config) must be of type array with keys as string diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index fe2a0648af683..16c09a96a75c2 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -114,7 +114,7 @@ static inline PHPTidyObj *php_tidy_fetch_object(zend_object *obj) { /* }}} */ /* {{{ ext/tidy prototypes */ -static zend_string *php_tidy_file_to_mem(const char *, bool); +static zend_string *php_tidy_file_to_mem(const zend_string *, bool); static void tidy_object_free_storage(zend_object *); static zend_object *tidy_object_new_node(zend_class_entry *); static zend_object *tidy_object_new_doc(zend_class_entry *); @@ -124,7 +124,6 @@ static void tidy_doc_update_properties(PHPTidyObj *); static void tidy_add_node_default_properties(PHPTidyObj *); static void *php_tidy_get_opt_val(const PHPTidyDoc *, TidyOption, TidyOptionType *); static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetypes); -static zend_result _php_tidy_set_tidy_opt(TidyDoc, const char *, zval *, uint32_t arg); static zend_result _php_tidy_apply_config_array(TidyDoc doc, const HashTable *ht_options, uint32_t arg); static PHP_INI_MH(php_tidy_set_clean_output); static void php_tidy_clean_output_start(const char *name, size_t name_len); @@ -216,58 +215,6 @@ static zend_result php_tidy_apply_config(TidyDoc doc, const zend_string *str_str return SUCCESS; } -static zend_result _php_tidy_set_tidy_opt(TidyDoc doc, const char *optname, zval *value, uint32_t arg) -{ - TidyOption opt = tidyGetOptionByName(doc, optname); - zend_string *str, *tmp_str; - zend_long lval; - - if (!opt) { - zend_argument_value_error(arg, "Unknown Tidy configuration option \"%s\"", optname); - return FAILURE; - } - -#if defined(HAVE_TIDYOPTGETCATEGORY) - if (tidyOptGetCategory(opt) == TidyInternalCategory) { -#else - if (tidyOptIsReadOnly(opt)) { -#endif - zend_argument_value_error(arg, "Attempting to set read-only option \"%s\"", optname); - return FAILURE; - } - - switch(tidyOptGetType(opt)) { - case TidyString: - str = zval_get_tmp_string(value, &tmp_str); - if (tidyOptSetValue(doc, tidyOptGetId(opt), ZSTR_VAL(str))) { - zend_tmp_string_release(tmp_str); - return SUCCESS; - } - zend_tmp_string_release(tmp_str); - break; - - case TidyInteger: - lval = zval_get_long(value); - if (tidyOptSetInt(doc, tidyOptGetId(opt), lval)) { - return SUCCESS; - } - break; - - case TidyBoolean: - lval = zval_get_long(value); - if (tidyOptSetBool(doc, tidyOptGetId(opt), lval)) { - return SUCCESS; - } - break; - - default: - php_error_docref(NULL, E_WARNING, "Unable to determine type of configuration option"); - break; - } - - return FAILURE; -} - static void tidy_create_node_object(zval *zv, PHPTidyDoc *ptdoc, TidyNode node) { object_init_ex(zv, tidy_ce_node); @@ -299,7 +246,7 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, bool is_file) Z_PARAM_BOOL(use_include_path) ZEND_PARSE_PARAMETERS_END(); - if (!(data = php_tidy_file_to_mem(ZSTR_VAL(arg1), use_include_path))) { + if (!(data = php_tidy_file_to_mem(arg1, use_include_path))) { RETURN_FALSE; } } else { @@ -381,12 +328,12 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, bool is_file) tidyRelease(doc); } -static zend_string *php_tidy_file_to_mem(const char *filename, bool use_include_path) +static zend_string *php_tidy_file_to_mem(const zend_string *filename, bool use_include_path) { php_stream *stream; zend_string *data = NULL; - if (!(stream = php_stream_open_wrapper(filename, "rb", (use_include_path ? USE_PATH : 0), NULL))) { + if (!(stream = php_stream_open_wrapper(ZSTR_VAL(filename), "rb", (use_include_path ? USE_PATH : 0), NULL))) { return NULL; } if ((data = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0)) == NULL) { @@ -720,28 +667,19 @@ static void *php_tidy_get_opt_val(const PHPTidyDoc *ptdoc, TidyOption opt, TidyO { *type = tidyOptGetType(opt); - switch (*type) { - case TidyString: { - const char *val = tidyOptGetValue(ptdoc->doc, tidyOptGetId(opt)); - if (val) { - return (void *) zend_string_init(val, strlen(val), 0); - } else { - return (void *) ZSTR_EMPTY_ALLOC(); - } + if (*type == TidyString) { + const char *val = tidyOptGetValue(ptdoc->doc, tidyOptGetId(opt)); + if (val) { + return (void *) zend_string_init(val, strlen(val), 0); + } else { + return (void *) ZSTR_EMPTY_ALLOC(); } - break; - - case TidyInteger: - return (void *) (uintptr_t) tidyOptGetInt(ptdoc->doc, tidyOptGetId(opt)); - break; - - case TidyBoolean: - return (void *) tidyOptGetBool(ptdoc->doc, tidyOptGetId(opt)); - break; + } else if (*type == TidyInteger) { + return (void *) (uintptr_t) tidyOptGetInt(ptdoc->doc, tidyOptGetId(opt)); + } else { + ZEND_ASSERT(*type == TidyBoolean); + return (void *) tidyOptGetBool(ptdoc->doc, tidyOptGetId(opt)); } - - /* should not happen */ - return NULL; } static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetypes node_type) @@ -776,31 +714,74 @@ static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetyp tidy_create_node_object(return_value, obj->ptdoc, node); } + +static bool php_tidy_set_tidy_opt(TidyDoc doc, const char *optname, zval *value, uint32_t arg) +{ + TidyOption opt = tidyGetOptionByName(doc, optname); + zend_long lval; + + if (!opt) { + zend_argument_value_error(arg, "Unknown Tidy configuration option \"%s\"", optname); + return false; + } + +#if defined(HAVE_TIDYOPTGETCATEGORY) + if (tidyOptGetCategory(opt) == TidyInternalCategory) { +#else + if (tidyOptIsReadOnly(opt)) { +#endif + zend_argument_value_error(arg, "Attempting to set read-only option \"%s\"", optname); + return false; + } + + TidyOptionType type = tidyOptGetType(opt); + if (type == TidyString) { + zend_string *tmp_str; + const zend_string *str = zval_get_tmp_string(value, &tmp_str); + const bool result = tidyOptSetValue(doc, tidyOptGetId(opt), ZSTR_VAL(str)); + if (UNEXPECTED(!result)) { + zend_argument_type_error(arg, "option \"%s\" does not accept \"%s\" as a value", optname, ZSTR_VAL(str)); + } + zend_tmp_string_release(tmp_str); + return result; + } else if (type == TidyInteger) { + lval = zval_get_long(value); + return tidyOptSetInt(doc, tidyOptGetId(opt), lval); + } else { + ZEND_ASSERT(type == TidyBoolean); + lval = zval_get_long(value); + return tidyOptSetBool(doc, tidyOptGetId(opt), lval); + } +} + static zend_result _php_tidy_apply_config_array(TidyDoc doc, const HashTable *ht_options, uint32_t arg) { zval *opt_val; zend_string *opt_name; if (!HT_IS_PACKED(ht_options)) { + bool has_failures = false; ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(ht_options, opt_name, opt_val) { if (opt_name == NULL) { zend_argument_type_error(arg, "must be of type array with keys as string"); return FAILURE; } - _php_tidy_set_tidy_opt(doc, ZSTR_VAL(opt_name), opt_val, arg); + has_failures = has_failures || !php_tidy_set_tidy_opt(doc, ZSTR_VAL(opt_name), opt_val, arg); } ZEND_HASH_FOREACH_END(); - return SUCCESS; + return has_failures ? FAILURE : SUCCESS; } else { zend_argument_type_error(arg, "must be of type array with keys as string"); return FAILURE; } } -static zend_result php_tidy_parse_string(PHPTidyObj *obj, const char *string, uint32_t len, const char *enc) +static zend_result php_tidy_parse_string(PHPTidyObj *obj, const zend_string *string, const char *enc) { TidyBuffer buf; - if(enc) { + ZEND_ASSERT(!ZEND_SIZE_T_UINT_OVFL(ZSTR_LEN(string))); + + if (enc) { if (tidySetCharEncoding(obj->ptdoc->doc, enc) < 0) { php_error_docref(NULL, E_WARNING, "Could not set encoding \"%s\"", enc); return FAILURE; @@ -810,9 +791,9 @@ static zend_result php_tidy_parse_string(PHPTidyObj *obj, const char *string, ui obj->ptdoc->initialized = true; tidyBufInit(&buf); - tidyBufAttach(&buf, (byte *) string, len); + tidyBufAttach(&buf, (byte *) ZSTR_VAL(string), (unsigned int) ZSTR_LEN(string)); if (tidyParseBuffer(obj->ptdoc->doc, &buf) < 0) { - php_error_docref(NULL, E_WARNING, "%s", obj->ptdoc->errbuf->bp); + php_error_docref(NULL, E_WARNING, "%s", (const char*) obj->ptdoc->errbuf->bp); return FAILURE; } tidy_doc_update_properties(obj); @@ -1016,7 +997,7 @@ PHP_FUNCTION(tidy_parse_string) obj = Z_TIDY_P(return_value); if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht, 2) != SUCCESS - || php_tidy_parse_string(obj, ZSTR_VAL(input), (uint32_t)ZSTR_LEN(input), enc) != SUCCESS) { + || php_tidy_parse_string(obj, input, enc) != SUCCESS) { zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -1069,7 +1050,7 @@ PHP_FUNCTION(tidy_parse_file) Z_PARAM_BOOL(use_include_path) ZEND_PARSE_PARAMETERS_END(); - if (!(contents = php_tidy_file_to_mem(ZSTR_VAL(inputfile), use_include_path))) { + if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path))) { php_error_docref(NULL, E_WARNING, "Cannot load \"%s\" into memory%s", ZSTR_VAL(inputfile), (use_include_path) ? " (using include path)" : ""); RETURN_FALSE; } @@ -1084,7 +1065,7 @@ PHP_FUNCTION(tidy_parse_file) obj = Z_TIDY_P(return_value); if (php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht, 2) != SUCCESS - || php_tidy_parse_string(obj, ZSTR_VAL(contents), (uint32_t)ZSTR_LEN(contents), enc) != SUCCESS) { + || php_tidy_parse_string(obj, contents, enc) != SUCCESS) { zval_ptr_dtor(return_value); RETVAL_FALSE; } @@ -1322,18 +1303,10 @@ PHP_FUNCTION(tidy_getopt) case TidyInteger: RETURN_LONG((zend_long)optval); - break; case TidyBoolean: RETURN_BOOL(optval); - break; - - default: - php_error_docref(NULL, E_WARNING, "Unable to determine type of configuration option"); - break; } - - RETURN_FALSE; } /* }}} */ @@ -1357,7 +1330,7 @@ PHP_METHOD(tidy, __construct) obj = Z_TIDY_P(ZEND_THIS); if (inputfile) { - if (!(contents = php_tidy_file_to_mem(ZSTR_VAL(inputfile), use_include_path))) { + if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path))) { zend_throw_error(zend_ce_exception, "Cannot load \"%s\" into memory%s", ZSTR_VAL(inputfile), (use_include_path) ? " (using include path)" : ""); RETURN_THROWS(); } @@ -1377,7 +1350,7 @@ PHP_METHOD(tidy, __construct) } zend_restore_error_handling(&error_handling); - php_tidy_parse_string(obj, ZSTR_VAL(contents), (uint32_t)ZSTR_LEN(contents), enc); + php_tidy_parse_string(obj, contents, enc); zend_string_release_ex(contents, 0); } @@ -1402,7 +1375,7 @@ PHP_METHOD(tidy, parseFile) obj = Z_TIDY_P(ZEND_THIS); - if (!(contents = php_tidy_file_to_mem(ZSTR_VAL(inputfile), use_include_path))) { + if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path))) { php_error_docref(NULL, E_WARNING, "Cannot load \"%s\" into memory%s", ZSTR_VAL(inputfile), (use_include_path) ? " (using include path)" : ""); RETURN_FALSE; } @@ -1414,7 +1387,7 @@ PHP_METHOD(tidy, parseFile) } RETVAL_BOOL(php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht, 2) == SUCCESS - && php_tidy_parse_string(obj, ZSTR_VAL(contents), (uint32_t)ZSTR_LEN(contents), enc) == SUCCESS); + && php_tidy_parse_string(obj, contents, enc) == SUCCESS); zend_string_release_ex(contents, 0); } @@ -1442,7 +1415,7 @@ PHP_METHOD(tidy, parseString) obj = Z_TIDY_P(ZEND_THIS); RETURN_BOOL(php_tidy_apply_config(obj->ptdoc->doc, options_str, options_ht, 2) == SUCCESS - && php_tidy_parse_string(obj, ZSTR_VAL(input), (uint32_t)ZSTR_LEN(input), enc) == SUCCESS); + && php_tidy_parse_string(obj, input, enc) == SUCCESS); } diff --git a/ext/tokenizer/tests/gh19507_eval.phpt b/ext/tokenizer/tests/gh19507_eval.phpt new file mode 100644 index 0000000000000..e731cf818afbd --- /dev/null +++ b/ext/tokenizer/tests/gh19507_eval.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19507: Corrupted result after recursive tokenization during token_get_all() (error handler with eval) +--EXTENSIONS-- +tokenizer +--FILE-- +getTokenName(), "\n"; +} +?> +--EXPECT-- +error handler called: Non-canonical cast (double) is deprecated, use the (float) cast instead +T_OPEN_TAG +T_DOUBLE_CAST +T_WHITESPACE +T_VARIABLE +; diff --git a/ext/tokenizer/tests/gh19507_throw.phpt b/ext/tokenizer/tests/gh19507_throw.phpt new file mode 100644 index 0000000000000..4449fe430538d --- /dev/null +++ b/ext/tokenizer/tests/gh19507_throw.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-19507: Corrupted result after recursive tokenization during token_get_all() (error handler with throw) +--EXTENSIONS-- +tokenizer +--FILE-- +getTokenName(), "\n"; +} +?> +--EXPECTF-- +Fatal error: Uncaught RuntimeException: error handler called: Non-canonical cast (double) is deprecated, use the (float) cast instead in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(%d, 'Non-canonical c...', '', 1) +#1 %s(%d): PhpToken::tokenize('= 0.9.9]) + PHP_EVAL_LIBLINE([$LIBURIPARSER_LIBS], [URI_SHARED_LIBADD]) + PHP_EVAL_INCLINE([$LIBURIPARSER_CFLAGS]) +fi -PHP_NEW_EXTENSION(uri, [php_lexbor.c php_uri.c php_uri_common.c $URIPARSER_SOURCES], [no],,[-I$ext_srcdir/$URIPARSER_DIR/include -DURI_STATIC_BUILD -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) +PHP_NEW_EXTENSION(uri, [php_uri.c php_uri_common.c uri_parser_rfc3986.c uri_parser_whatwg.c uri_parser_php_parse_url.c $URIPARSER_SOURCES], [no],,[$URI_CFLAGS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) PHP_ADD_EXTENSION_DEP(uri, lexbor) -PHP_ADD_BUILD_DIR($ext_builddir/$URIPARSER_DIR/src $ext_builddir/$URIPARSER_DIR/include) + +if test "$PHP_EXTERNAL_URIPARSER" = "no"; then + PHP_ADD_BUILD_DIR($ext_builddir/$URIPARSER_DIR/src $ext_builddir/$URIPARSER_DIR/include) + PHP_ADD_INCLUDE([$ext_srcdir/$URIPARSER_DIR/include]) +fi diff --git a/ext/uri/config.w32 b/ext/uri/config.w32 index 9c6af0cc5fa7b..97c10caf098f6 100644 --- a/ext/uri/config.w32 +++ b/ext/uri/config.w32 @@ -1,9 +1,12 @@ -EXTENSION("uri", "php_lexbor.c php_uri.c php_uri_common.c", false /* never shared */, "/I ext/lexbor /I ext/uri/uriparser/include /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); +EXTENSION("uri", "php_uri.c php_uri_common.c uri_parser_rfc3986.c uri_parser_whatwg.c uri_parser_php_parse_url.c", false /* never shared */, "/I ext/lexbor /I ext/uri/uriparser/include /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); AC_DEFINE("URI_ENABLE_ANSI", 1, "Define to 1 for enabling ANSI support of uriparser.") AC_DEFINE("URI_NO_UNICODE", 1, "Define to 1 for disabling unicode support of uriparser.") ADD_FLAG("CFLAGS_URI", "/D URI_STATIC_BUILD"); ADD_EXTENSION_DEP('uri', 'lexbor'); -ADD_SOURCES("ext/uri/uriparser/src", "UriCommon.c UriCompare.c UriEscape.c UriFile.c UriIp4.c UriIp4Base.c UriMemory.c UriNormalize.c UriNormalizeBase.c UriParse.c UriParseBase.c UriQuery.c UriRecompose.c UriShorten.c", "uri"); -PHP_INSTALL_HEADERS("ext/uri", "php_lexbor.h php_uri.h php_uri_common.h uriparser/src uriparser/include"); +ADD_SOURCES("ext/uri/uriparser/src", "UriCommon.c UriCompare.c UriCopy.c UriEscape.c UriFile.c UriIp4.c UriIp4Base.c \ + UriMemory.c UriNormalize.c UriNormalizeBase.c UriParse.c UriParseBase.c UriQuery.c UriRecompose.c UriResolve.c \ + UriSetFragment.c UriSetHostAuto.c UriSetHostCommon.c UriSetHostIp4.c UriSetHostIp6.c UriSetHostIpFuture.c UriSetHostRegName.c \ + UriSetPath.c UriSetPort.c UriSetQuery.c UriSetScheme.c UriSetUserInfo.c UriShorten.c UriVersion.c", "uri"); +PHP_INSTALL_HEADERS("ext/uri", "php_uri.h php_uri_common.h uri_parser_rfc3986.h uri_parser_whatwg.h uri_parser_php_parse_url.h uriparser/src uriparser/include"); diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 5b2e21b1625a3..e5436d7f1e369 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -26,11 +26,14 @@ #include "ext/standard/info.h" #include "php_uri.h" -#include "php_uri_common.h" -#include "php_lexbor.h" +#include "uri_parser_whatwg.h" +#include "uri_parser_rfc3986.h" +#include "uri_parser_php_parse_url.h" #include "php_uri_arginfo.h" -#include "uriparser/src/UriConfig.h" +#include "uriparser/UriBase.h" +zend_class_entry *uri_rfc3986_uri_ce; +zend_object_handlers uri_rfc3986_uri_object_handlers; zend_class_entry *uri_whatwg_url_ce; zend_object_handlers uri_whatwg_uri_object_handlers; zend_class_entry *uri_comparison_mode_ce; @@ -40,19 +43,12 @@ zend_class_entry *uri_whatwg_invalid_url_exception_ce; zend_class_entry *uri_whatwg_url_validation_error_type_ce; zend_class_entry *uri_whatwg_url_validation_error_ce; -#define URIPARSER_VERSION PACKAGE_VERSION - static const zend_module_dep uri_deps[] = { ZEND_MOD_REQUIRED("lexbor") ZEND_MOD_END }; -static zend_array uri_handlers; - -static uri_handler_t *uri_handler_by_name(const char *handler_name, size_t handler_name_len) -{ - return zend_hash_str_find_ptr(&uri_handlers, handler_name, handler_name_len); -} +static zend_array uri_parsers; static HashTable *uri_get_debug_properties(zend_object *object) { @@ -62,107 +58,232 @@ static HashTable *uri_get_debug_properties(zend_object *object) HashTable *std_properties = zend_std_get_properties(object); HashTable *result = zend_array_dup(std_properties); - if (UNEXPECTED(internal_uri->uri == NULL)) { + const php_uri_parser * const parser = internal_uri->parser; + void * const uri = internal_uri->uri; + + if (UNEXPECTED(uri == NULL)) { return result; } - const uri_property_handlers_t property_handlers = internal_uri->handler->property_handlers; - zval tmp; - if (property_handlers.scheme.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.scheme.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_SCHEME), &tmp); } - if (property_handlers.username.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.username.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_USERNAME), &tmp); } - if (property_handlers.password.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.password.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PASSWORD), &tmp); } - if (property_handlers.host.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.host.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_HOST), &tmp); } - if (property_handlers.port.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.port.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PORT), &tmp); } - if (property_handlers.path.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.path.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PATH), &tmp); } - if (property_handlers.query.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.query.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_QUERY), &tmp); } - if (property_handlers.fragment.read_func(internal_uri, URI_COMPONENT_READ_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.fragment.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_FRAGMENT), &tmp); } return result; } -PHP_METHOD(Uri_WhatWg_InvalidUrlException, __construct) +PHPAPI const php_uri_parser *php_uri_get_parser(zend_string *uri_parser_name) { - zend_string *message = NULL; - zval *errors = NULL; - zend_long code = 0; - zval *previous = NULL; + if (uri_parser_name == NULL) { + return zend_hash_str_find_ptr(&uri_parsers, PHP_URI_PARSER_PHP_PARSE_URL, sizeof(PHP_URI_PARSER_PHP_PARSE_URL) - 1); + } - ZEND_PARSE_PARAMETERS_START(0, 4) - Z_PARAM_OPTIONAL - Z_PARAM_STR(message) - Z_PARAM_ARRAY(errors) - Z_PARAM_LONG(code) - Z_PARAM_OBJECT_OF_CLASS_OR_NULL(previous, zend_ce_throwable) - ZEND_PARSE_PARAMETERS_END(); + return zend_hash_find_ptr(&uri_parsers, uri_parser_name); +} - if (zend_update_exception_properties(INTERNAL_FUNCTION_PARAM_PASSTHRU, message, code, previous) == FAILURE) { - RETURN_THROWS(); - } +ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, bool silent) +{ + uri_internal_t *internal_uri = emalloc(sizeof(*internal_uri)); + internal_uri->parser = uri_parser; + internal_uri->uri = uri_parser->parse(uri_str, uri_str_len, NULL, NULL, silent); - if (errors == NULL) { - zval tmp; - ZVAL_EMPTY_ARRAY(&tmp); - zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), &tmp); - } else { - zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), errors); - } - if (EG(exception)) { - RETURN_THROWS(); + if (UNEXPECTED(internal_uri->uri == NULL)) { + efree(internal_uri); + return NULL; } + + return internal_uri; } -PHP_METHOD(Uri_WhatWg_UrlValidationError, __construct) +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - zend_string *context; - zval *type; - bool failure; + return internal_uri->parser->property_handler.scheme.read(internal_uri->uri, read_mode, zv); +} - ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_STR(context) - Z_PARAM_OBJECT_OF_CLASS(type, uri_whatwg_url_validation_error_type_ce) - Z_PARAM_BOOL(failure) - ZEND_PARSE_PARAMETERS_END(); +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.username.read(internal_uri->uri, read_mode, zv); +} - zend_update_property_str(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("context"), context); - if (EG(exception)) { - RETURN_THROWS(); +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.password.read(internal_uri->uri, read_mode, zv); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.host.read(internal_uri->uri, read_mode, zv); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.port.read(internal_uri->uri, read_mode, zv); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.path.read(internal_uri->uri, read_mode, zv); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.query.read(internal_uri->uri, read_mode, zv); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) +{ + return internal_uri->parser->property_handler.fragment.read(internal_uri->uri, read_mode, zv); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(uri_internal_t *internal_uri) +{ + internal_uri->parser->free(internal_uri->uri); + internal_uri->uri = NULL; + internal_uri->parser = NULL; + efree(internal_uri); +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct( + const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, php_uri_component_read_mode read_mode, bool silent +) { + uri_internal_t *uri_internal = php_uri_parse(uri_parser, uri_str, uri_str_len, silent); + if (uri_internal == NULL) { + return NULL; } - zend_update_property_ex(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_TYPE), type); - if (EG(exception)) { - RETURN_THROWS(); + php_uri *uri = ecalloc(1, sizeof(*uri)); + zval tmp; + zend_result result; + + result = php_uri_get_scheme(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_STRING) { + uri->scheme = Z_STR(tmp); } - zval failure_zv; - ZVAL_BOOL(&failure_zv, failure); - zend_update_property(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("failure"), &failure_zv); - if (EG(exception)) { - RETURN_THROWS(); + result = php_uri_get_username(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_STRING) { + uri->user = Z_STR(tmp); + } + + result = php_uri_get_password(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_STRING) { + uri->password = Z_STR(tmp); } + + result = php_uri_get_host(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_STRING) { + uri->host = Z_STR(tmp); + } + + result = php_uri_get_port(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_LONG) { + uri->port = Z_LVAL(tmp); + } + + result = php_uri_get_path(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_STRING) { + uri->path = Z_STR(tmp); + } + + result = php_uri_get_query(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_STRING) { + uri->query = Z_STR(tmp); + } + + result = php_uri_get_fragment(uri_internal, read_mode, &tmp); + if (result == FAILURE) { + goto error; + } + if (Z_TYPE(tmp) == IS_STRING) { + uri->fragment = Z_STR(tmp); + } + + php_uri_free(uri_internal); + + return uri; + +error: + php_uri_free(uri_internal); + php_uri_struct_free(uri); + + return NULL; +} + +ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_struct_free(php_uri *uri) +{ + if (uri->scheme) { + zend_string_release(uri->scheme); + } + if (uri->user) { + zend_string_release(uri->user); + } + if (uri->password) { + zend_string_release(uri->password); + } + if (uri->host) { + zend_string_release(uri->host); + } + if (uri->path) { + zend_string_release(uri->path); + } + if (uri->query) { + zend_string_release(uri->query); + } + if (uri->fragment) { + zend_string_release(uri->fragment); + } + + efree(uri); } /** @@ -188,28 +309,48 @@ static zend_result pass_errors_by_ref_and_free(zval *errors_zv, zval *errors) ZEND_TRY_ASSIGN_REF_ARR(errors_zv, Z_ARRVAL_P(errors)); if (EG(exception)) { - zval_ptr_dtor(errors); return FAILURE; } return SUCCESS; } -PHPAPI void php_uri_instantiate_uri( - INTERNAL_FUNCTION_PARAMETERS, const uri_handler_t *handler, const zend_string *uri_str, const zend_object *base_url_object, - bool should_throw, bool should_update_this_object, zval *errors_zv +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( + INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const zend_object *base_url_object, + bool should_throw, bool should_update_this_object, zval *errors_zv ) { + + uri_object_t *uri_object; + if (should_update_this_object) { + uri_object = Z_URI_OBJECT_P(ZEND_THIS); + if (uri_object->internal.uri != NULL) { + zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name)); + RETURN_THROWS(); + } + } else { + if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) { + object_init_ex(return_value, Z_CE_P(ZEND_THIS)); + } else { + object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS)); + } + uri_object = Z_URI_OBJECT_P(return_value); + } + + const php_uri_parser *uri_parser = uri_object->internal.parser; + zval errors; ZVAL_UNDEF(&errors); void *base_url = NULL; if (base_url_object != NULL) { + ZEND_ASSERT(base_url_object->ce == uri_object->std.ce); uri_internal_t *internal_base_url = uri_internal_from_obj(base_url_object); URI_ASSERT_INITIALIZATION(internal_base_url); + ZEND_ASSERT(internal_base_url->parser == uri_parser); base_url = internal_base_url->uri; } - void *uri = handler->parse_uri(uri_str, base_url, should_throw || errors_zv != NULL ? &errors : NULL, !should_throw); + void *uri = uri_parser->parse(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), base_url, errors_zv != NULL ? &errors : NULL, !should_throw); if (UNEXPECTED(uri == NULL)) { if (should_throw) { zval_ptr_dtor(&errors); @@ -218,28 +359,128 @@ PHPAPI void php_uri_instantiate_uri( if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) { RETURN_THROWS(); } + zval_ptr_dtor(return_value); RETURN_NULL(); } } if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) { + uri_parser->free(uri); RETURN_THROWS(); } - uri_object_t *uri_object; - if (should_update_this_object) { - uri_object = Z_URI_OBJECT_P(ZEND_THIS); + uri_object->internal.uri = uri; +} + +static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) +{ + zend_string *uri_str; + zend_object *base_url_object = NULL; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_PATH_STR(uri_str) + Z_PARAM_OPTIONAL + Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, uri_rfc3986_uri_ce) + ZEND_PARSE_PARAMETERS_END(); + + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, base_url_object, is_constructor, is_constructor, NULL); +} + +static bool is_list_of_whatwg_validation_errors(const HashTable *array) +{ + if (!zend_array_is_list(array)) { + return false; + } + + ZEND_HASH_FOREACH_VAL(array, zval *val) { + /* Do not allow references as they may change types after checking. */ + + if (Z_TYPE_P(val) != IS_OBJECT) { + return false; + } + + if (!instanceof_function(Z_OBJCE_P(val), uri_whatwg_url_validation_error_ce)) { + return false; + } + } ZEND_HASH_FOREACH_END(); + + return true; +} + +PHP_METHOD(Uri_Rfc3986_Uri, parse) +{ + create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); +} + +PHP_METHOD(Uri_Rfc3986_Uri, __construct) +{ + create_rfc3986_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); +} + +PHP_METHOD(Uri_WhatWg_InvalidUrlException, __construct) +{ + zend_string *message = NULL; + zval *errors = NULL; + zend_long code = 0; + zval *previous = NULL; + + ZEND_PARSE_PARAMETERS_START(0, 4) + Z_PARAM_OPTIONAL + Z_PARAM_STR(message) + Z_PARAM_ARRAY(errors) + Z_PARAM_LONG(code) + Z_PARAM_OBJECT_OF_CLASS_OR_NULL(previous, zend_ce_throwable) + ZEND_PARSE_PARAMETERS_END(); + + if (zend_update_exception_properties(INTERNAL_FUNCTION_PARAM_PASSTHRU, message, code, previous) == FAILURE) { + RETURN_THROWS(); + } + + if (errors == NULL) { + zval tmp; + ZVAL_EMPTY_ARRAY(&tmp); + zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), &tmp); } else { - if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) { - object_init_ex(return_value, Z_CE_P(ZEND_THIS)); - } else { - object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS)); + if (!is_list_of_whatwg_validation_errors(Z_ARR_P(errors))) { + zend_argument_value_error(2, "must be a list of %s", ZSTR_VAL(uri_whatwg_url_validation_error_ce->name)); + RETURN_THROWS(); } - uri_object = Z_URI_OBJECT_P(return_value); + + zend_update_property(uri_whatwg_invalid_url_exception_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("errors"), errors); + } + if (EG(exception)) { + RETURN_THROWS(); } +} - uri_object->internal.handler = handler; - uri_object->internal.uri = uri; +PHP_METHOD(Uri_WhatWg_UrlValidationError, __construct) +{ + zend_string *context; + zval *type; + bool failure; + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(context) + Z_PARAM_OBJECT_OF_CLASS(type, uri_whatwg_url_validation_error_type_ce) + Z_PARAM_BOOL(failure) + ZEND_PARSE_PARAMETERS_END(); + + zend_update_property_str(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("context"), context); + if (EG(exception)) { + RETURN_THROWS(); + } + + zend_update_property_ex(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZSTR_KNOWN(ZEND_STR_TYPE), type); + if (EG(exception)) { + RETURN_THROWS(); + } + + zval failure_zv; + ZVAL_BOOL(&failure_zv, failure); + zend_update_property(uri_whatwg_url_validation_error_ce, Z_OBJ_P(ZEND_THIS), ZEND_STRL("failure"), &failure_zv); + if (EG(exception)) { + RETURN_THROWS(); + } } static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) @@ -255,7 +496,7 @@ static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) Z_PARAM_ZVAL(errors) ZEND_PARSE_PARAMETERS_END(); - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &lexbor_uri_handler, uri_str, base_url_object, is_constructor, is_constructor, errors); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, base_url_object, is_constructor, is_constructor, errors); } PHP_METHOD(Uri_WhatWg_Url, parse) @@ -268,6 +509,175 @@ PHP_METHOD(Uri_WhatWg_Url, __construct) create_whatwg_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); } +PHP_METHOD(Uri_Rfc3986_Uri, getScheme) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawScheme) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withScheme) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME); +} + +static void rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAMETERS, php_uri_component_read_mode read_mode) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); + URI_ASSERT_INITIALIZATION(internal_uri); + + if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(internal_uri->uri, read_mode, return_value) == FAILURE)) { + zend_throw_error(NULL, "The userinfo component cannot be retrieved"); + RETURN_THROWS(); + } +} + +PHP_METHOD(Uri_Rfc3986_Uri, getUserInfo) +{ + rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawUserInfo) +{ + rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo) +{ + zend_string *value; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH_STR_OR_NULL(value) + ZEND_PARSE_PARAMETERS_END(); + + zval zv; + if (value == NULL) { + ZVAL_NULL(&zv); + } else { + ZVAL_STR(&zv, value); + } + + zend_object *old_object = Z_OBJ_P(ZEND_THIS); + uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); + URI_ASSERT_INITIALIZATION(internal_uri); + + zend_object *new_object = old_object->handlers->clone_obj(old_object); + if (new_object == NULL) { + RETURN_THROWS(); + } + + /* Assign the object early. The engine will take care of destruction in + * case of an exception being thrown. */ + RETVAL_OBJ(new_object); + + uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); + URI_ASSERT_INITIALIZATION(new_internal_uri); + + if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_internal_uri->uri, &zv, NULL) == FAILURE)) { + RETURN_THROWS(); + } +} + +PHP_METHOD(Uri_Rfc3986_Uri, getUsername) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawUsername) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getPassword) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawPassword) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getHost) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawHost) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withHost) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getPort) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withPort) +{ + uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PORT); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getPath) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawPath) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withPath) +{ + uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PATH); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getQuery) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawQuery) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withQuery) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_QUERY); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getFragment) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); +} + +PHP_METHOD(Uri_Rfc3986_Uri, getRawFragment) +{ + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_RAW); +} + +PHP_METHOD(Uri_Rfc3986_Uri, withFragment) +{ + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT); +} + +static void throw_cannot_recompose_uri_to_string(zend_object *object) +{ + zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to a string", ZSTR_VAL(object->ce->name)); +} + static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, zend_object *comparison_mode) { zend_object *this_object = Z_OBJ_P(ZEND_THIS); @@ -290,18 +700,18 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, z exclude_fragment = zend_string_equals_literal(Z_STR_P(case_name), "ExcludeFragment"); } - zend_string *this_str = this_internal_uri->handler->uri_to_string( - this_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_ASCII, exclude_fragment); + zend_string *this_str = this_internal_uri->parser->to_string( + this_internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment); if (this_str == NULL) { - zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to string", ZSTR_VAL(this_object->ce->name)); + throw_cannot_recompose_uri_to_string(this_object); RETURN_THROWS(); } - zend_string *that_str = that_internal_uri->handler->uri_to_string( - that_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_ASCII, exclude_fragment); + zend_string *that_str = that_internal_uri->parser->to_string( + that_internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, exclude_fragment); if (that_str == NULL) { zend_string_release(this_str); - zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to string", ZSTR_VAL(that_object->ce->name)); + throw_cannot_recompose_uri_to_string(that_object); RETURN_THROWS(); } @@ -311,7 +721,96 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, z zend_string_release(that_str); } -static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_name) +PHP_METHOD(Uri_Rfc3986_Uri, equals) +{ + zend_object *that_object; + zend_object *comparison_mode = NULL; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_OBJ_OF_CLASS(that_object, uri_rfc3986_uri_ce) + Z_PARAM_OPTIONAL + Z_PARAM_OBJ_OF_CLASS(comparison_mode, uri_comparison_mode_ce) + ZEND_PARSE_PARAMETERS_END(); + + uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, comparison_mode); +} + +PHP_METHOD(Uri_Rfc3986_Uri, toRawString) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_object *this_object = Z_OBJ_P(ZEND_THIS); + uri_internal_t *internal_uri = uri_internal_from_obj(this_object); + URI_ASSERT_INITIALIZATION(internal_uri); + + zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false); + if (uri_str == NULL) { + throw_cannot_recompose_uri_to_string(this_object); + RETURN_THROWS(); + } + + RETURN_STR(uri_str); +} + +PHP_METHOD(Uri_Rfc3986_Uri, toString) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_object *this_object = Z_OBJ_P(ZEND_THIS); + uri_internal_t *internal_uri = uri_internal_from_obj(this_object); + URI_ASSERT_INITIALIZATION(internal_uri); + + zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, false); + if (uri_str == NULL) { + throw_cannot_recompose_uri_to_string(this_object); + RETURN_THROWS(); + } + + RETURN_STR(uri_str); +} + +PHP_METHOD(Uri_Rfc3986_Uri, resolve) +{ + zend_string *uri_str; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_PATH_STR(uri_str) + ZEND_PARSE_PARAMETERS_END(); + + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, Z_OBJ_P(ZEND_THIS), true, false, NULL); +} + +PHP_METHOD(Uri_Rfc3986_Uri, __serialize) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_object *this_object = Z_OBJ_P(ZEND_THIS); + uri_internal_t *internal_uri = uri_internal_from_obj(this_object); + URI_ASSERT_INITIALIZATION(internal_uri); + + /* Serialize state: "uri" key in the first array */ + zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false); + if (uri_str == NULL) { + throw_cannot_recompose_uri_to_string(this_object); + RETURN_THROWS(); + } + zval tmp; + ZVAL_STR(&tmp, uri_str); + + array_init(return_value); + + zval arr; + array_init(&arr); + zend_hash_str_add_new(Z_ARRVAL(arr), URI_SERIALIZED_PROPERTY_NAME, sizeof(URI_SERIALIZED_PROPERTY_NAME) - 1, &tmp); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr); + + /* Serialize regular properties: second array */ + ZVAL_ARR(&arr, this_object->handlers->get_properties(this_object)); + Z_TRY_ADDREF(arr); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr); +} + +static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS) { HashTable *data; @@ -347,11 +846,13 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_na } uri_internal_t *internal_uri = uri_internal_from_obj(object); - internal_uri->handler = uri_handler_by_name(handler_name, strlen(handler_name)); if (internal_uri->uri != NULL) { - internal_uri->handler->free_uri(internal_uri->uri); + /* Intentionally throw two exceptions for proper chaining. */ + zend_throw_error(NULL, "Cannot modify readonly object of class %s", ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name)); + zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); + RETURN_THROWS(); } - internal_uri->uri = internal_uri->handler->parse_uri(Z_STR_P(uri_zv), NULL, NULL, true); + internal_uri->uri = internal_uri->parser->parse(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true); if (internal_uri->uri == NULL) { zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); RETURN_THROWS(); @@ -371,89 +872,53 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_na } } -PHP_METHOD(Uri_WhatWg_Url, getScheme) +PHP_METHOD(Uri_Rfc3986_Uri, __unserialize) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME, URI_COMPONENT_READ_NORMALIZED_ASCII); + uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU); } -PHP_METHOD(Uri_WhatWg_Url, withScheme) +PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo) { - uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_SCHEME); + ZEND_PARSE_PARAMETERS_NONE(); + + zend_object *object = Z_OBJ_P(ZEND_THIS); + + RETURN_ARR(uri_get_debug_properties(object)); } -PHP_METHOD(Uri_WhatWg_Url, getUsername) +PHP_METHOD(Uri_WhatWg_Url, getScheme) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME, URI_COMPONENT_READ_NORMALIZED_ASCII); + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); } -PHP_METHOD(Uri_WhatWg_Url, withUsername) +PHP_METHOD(Uri_WhatWg_Url, withScheme) { - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_USERNAME); + uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_SCHEME); } -PHP_METHOD(Uri_WhatWg_Url, getPassword) +PHP_METHOD(Uri_WhatWg_Url, withUsername) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PASSWORD, URI_COMPONENT_READ_NORMALIZED_ASCII); + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_USERNAME); } PHP_METHOD(Uri_WhatWg_Url, withPassword) { - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PASSWORD); + uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_PASSWORD); } PHP_METHOD(Uri_WhatWg_Url, getAsciiHost) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_NORMALIZED_ASCII); + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII); } PHP_METHOD(Uri_WhatWg_Url, getUnicodeHost) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST, URI_COMPONENT_READ_NORMALIZED_UNICODE); -} - -PHP_METHOD(Uri_WhatWg_Url, withHost) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_HOST); -} - -PHP_METHOD(Uri_WhatWg_Url, getPort) -{ - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT, URI_COMPONENT_READ_NORMALIZED_ASCII); -} - -PHP_METHOD(Uri_WhatWg_Url, withPort) -{ - uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PORT); -} - -PHP_METHOD(Uri_WhatWg_Url, getPath) -{ - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH, URI_COMPONENT_READ_NORMALIZED_ASCII); -} - -PHP_METHOD(Uri_WhatWg_Url, withPath) -{ - uri_write_component_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_PATH); -} - -PHP_METHOD(Uri_WhatWg_Url, getQuery) -{ - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY, URI_COMPONENT_READ_NORMALIZED_ASCII); -} - -PHP_METHOD(Uri_WhatWg_Url, withQuery) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_QUERY); + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_HOST, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE); } PHP_METHOD(Uri_WhatWg_Url, getFragment) { - uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT, URI_COMPONENT_READ_NORMALIZED_ASCII); -} - -PHP_METHOD(Uri_WhatWg_Url, withFragment) -{ - uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PROPERTY_NAME_FRAGMENT); + uri_read_component(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PROPERTY_NAME_FRAGMENT, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE); } PHP_METHOD(Uri_WhatWg_Url, equals) @@ -478,7 +943,7 @@ PHP_METHOD(Uri_WhatWg_Url, toUnicodeString) uri_internal_t *internal_uri = uri_internal_from_obj(this_object); URI_ASSERT_INITIALIZATION(internal_uri); - RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_UNICODE, false)); + RETURN_STR(internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE, false)); } PHP_METHOD(Uri_WhatWg_Url, toAsciiString) @@ -489,7 +954,7 @@ PHP_METHOD(Uri_WhatWg_Url, toAsciiString) uri_internal_t *internal_uri = uri_internal_from_obj(this_object); URI_ASSERT_INITIALIZATION(internal_uri); - RETURN_STR(internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false)); + RETURN_STR(internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false)); } PHP_METHOD(Uri_WhatWg_Url, resolve) @@ -503,11 +968,7 @@ PHP_METHOD(Uri_WhatWg_Url, resolve) Z_PARAM_ZVAL(errors) ZEND_PARSE_PARAMETERS_END(); - zend_object *this_object = Z_OBJ_P(ZEND_THIS); - uri_internal_t *internal_uri = uri_internal_from_obj(this_object); - URI_ASSERT_INITIALIZATION(internal_uri); - - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->handler, uri_str, this_object, true, false, errors); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, Z_OBJ_P(ZEND_THIS), true, false, errors); } PHP_METHOD(Uri_WhatWg_Url, __serialize) @@ -519,9 +980,9 @@ PHP_METHOD(Uri_WhatWg_Url, __serialize) URI_ASSERT_INITIALIZATION(internal_uri); /* Serialize state: "uri" key in the first array */ - zend_string *uri_str = internal_uri->handler->uri_to_string(internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false); + zend_string *uri_str = internal_uri->parser->to_string(internal_uri->uri, PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, false); if (uri_str == NULL) { - zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to string", ZSTR_VAL(this_object->ce->name)); + throw_cannot_recompose_uri_to_string(this_object); RETURN_THROWS(); } zval tmp; @@ -542,7 +1003,7 @@ PHP_METHOD(Uri_WhatWg_Url, __serialize) PHP_METHOD(Uri_WhatWg_Url, __unserialize) { - uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU, URI_PARSER_WHATWG); + uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU); } PHP_METHOD(Uri_WhatWg_Url, __debugInfo) @@ -554,43 +1015,50 @@ PHP_METHOD(Uri_WhatWg_Url, __debugInfo) RETURN_ARR(uri_get_debug_properties(object)); } -static zend_object *uri_create_object_handler(zend_class_entry *class_type) +PHPAPI uri_object_t *php_uri_object_create(zend_class_entry *class_type, const php_uri_parser *parser) { - uri_object_t *uri_object = zend_object_alloc(sizeof(uri_object_t), class_type); + uri_object_t *uri_object = zend_object_alloc(sizeof(*uri_object), class_type); zend_object_std_init(&uri_object->std, class_type); object_properties_init(&uri_object->std, class_type); - return &uri_object->std; + uri_object->internal = (uri_internal_t){ + .parser = parser, + .uri = NULL, + }; + + return uri_object; } -static void uri_free_obj_handler(zend_object *object) +static zend_object *php_uri_object_create_rfc3986(zend_class_entry *ce) { - uri_object_t *uri_object = uri_object_from_obj(object); + return &php_uri_object_create(ce, &php_uri_parser_rfc3986)->std; +} - if (UNEXPECTED(uri_object->internal.uri != NULL)) { - uri_object->internal.handler->free_uri(uri_object->internal.uri); - uri_object->internal.handler = NULL; - uri_object->internal.uri = NULL; - } +static zend_object *php_uri_object_create_whatwg(zend_class_entry *ce) +{ + return &php_uri_object_create(ce, &php_uri_parser_whatwg)->std; +} + +PHPAPI void php_uri_object_handler_free(zend_object *object) +{ + uri_object_t *uri_object = uri_object_from_obj(object); + uri_object->internal.parser->free(uri_object->internal.uri); zend_object_std_dtor(&uri_object->std); } -zend_object *uri_clone_obj_handler(zend_object *object) +PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object) { uri_object_t *uri_object = uri_object_from_obj(object); uri_internal_t *internal_uri = uri_internal_from_obj(object); URI_ASSERT_INITIALIZATION(internal_uri); - zend_object *new_object = uri_create_object_handler(object->ce); - ZEND_ASSERT(new_object != NULL); - uri_object_t *new_uri_object = uri_object_from_obj(new_object); + uri_object_t *new_uri_object = uri_object_from_obj(object->ce->create_object(object->ce)); + ZEND_ASSERT(new_uri_object->internal.parser == internal_uri->parser); - new_uri_object->internal.handler = internal_uri->handler; - - void *uri = internal_uri->handler->clone_uri(internal_uri->uri); + void *uri = internal_uri->parser->clone(internal_uri->uri); ZEND_ASSERT(uri != NULL); new_uri_object->internal.uri = uri; @@ -600,27 +1068,17 @@ zend_object *uri_clone_obj_handler(zend_object *object) return &new_uri_object->std; } -PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers) -{ - ce->create_object = uri_create_object_handler; - ce->default_object_handlers = object_handlers; - memcpy(object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - object_handlers->offset = XtOffsetOf(uri_object_t, std); - object_handlers->free_obj = uri_free_obj_handler; - object_handlers->clone_obj = uri_clone_obj_handler; -} - -zend_result uri_handler_register(const uri_handler_t *uri_handler) +PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser) { - zend_string *key = zend_string_init_interned(uri_handler->name, strlen(uri_handler->name), 1); + zend_string *key = zend_string_init_interned(uri_parser->name, strlen(uri_parser->name), true); - ZEND_ASSERT(uri_handler->name != NULL); - ZEND_ASSERT(uri_handler->parse_uri != NULL); - ZEND_ASSERT(uri_handler->clone_uri != NULL); - ZEND_ASSERT(uri_handler->uri_to_string != NULL); - ZEND_ASSERT(uri_handler->free_uri != NULL); + ZEND_ASSERT(uri_parser->name != NULL); + ZEND_ASSERT(uri_parser->parse != NULL); + ZEND_ASSERT(uri_parser->clone != NULL || strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0); + ZEND_ASSERT(uri_parser->to_string != NULL || strcmp(uri_parser->name, PHP_URI_PARSER_PHP_PARSE_URL) == 0); + ZEND_ASSERT(uri_parser->free != NULL); - zend_result result = zend_hash_add_ptr(&uri_handlers, key, (void *) uri_handler) != NULL ? SUCCESS : FAILURE; + zend_result result = zend_hash_add_ptr(&uri_parsers, key, (void *) uri_parser) != NULL ? SUCCESS : FAILURE; zend_string_release_ex(key, true); @@ -629,8 +1087,21 @@ zend_result uri_handler_register(const uri_handler_t *uri_handler) static PHP_MINIT_FUNCTION(uri) { + uri_rfc3986_uri_ce = register_class_Uri_Rfc3986_Uri(); + uri_rfc3986_uri_ce->create_object = php_uri_object_create_rfc3986; + uri_rfc3986_uri_ce->default_object_handlers = &uri_rfc3986_uri_object_handlers; + memcpy(&uri_rfc3986_uri_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + uri_rfc3986_uri_object_handlers.offset = XtOffsetOf(uri_object_t, std); + uri_rfc3986_uri_object_handlers.free_obj = php_uri_object_handler_free; + uri_rfc3986_uri_object_handlers.clone_obj = php_uri_object_handler_clone; + uri_whatwg_url_ce = register_class_Uri_WhatWg_Url(); - php_uri_implementation_set_object_handlers(uri_whatwg_url_ce, &uri_whatwg_uri_object_handlers); + uri_whatwg_url_ce->create_object = php_uri_object_create_whatwg; + uri_whatwg_url_ce->default_object_handlers = &uri_whatwg_uri_object_handlers; + memcpy(&uri_whatwg_uri_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + uri_whatwg_uri_object_handlers.offset = XtOffsetOf(uri_object_t, std); + uri_whatwg_uri_object_handlers.free_obj = php_uri_object_handler_free; + uri_whatwg_uri_object_handlers.clone_obj = php_uri_object_handler_clone; uri_comparison_mode_ce = register_class_Uri_UriComparisonMode(); uri_exception_ce = register_class_Uri_UriException(zend_ce_exception); @@ -639,9 +1110,17 @@ static PHP_MINIT_FUNCTION(uri) uri_whatwg_url_validation_error_ce = register_class_Uri_WhatWg_UrlValidationError(); uri_whatwg_url_validation_error_type_ce = register_class_Uri_WhatWg_UrlValidationErrorType(); - zend_hash_init(&uri_handlers, 4, NULL, NULL, true); + zend_hash_init(&uri_parsers, 4, NULL, NULL, true); + + if (php_uri_parser_register(&php_uri_parser_rfc3986) == FAILURE) { + return FAILURE; + } + + if (php_uri_parser_register(&php_uri_parser_whatwg) == FAILURE) { + return FAILURE; + } - if (uri_handler_register(&lexbor_uri_handler) == FAILURE) { + if (php_uri_parser_register(&php_uri_parser_php_parse_url) == FAILURE) { return FAILURE; } @@ -651,30 +1130,37 @@ static PHP_MINIT_FUNCTION(uri) static PHP_MINFO_FUNCTION(uri) { php_info_print_table_start(); - php_info_print_table_row(2, "uri support", "active"); - php_info_print_table_row(2, "uriparser library version", URIPARSER_VERSION); + php_info_print_table_row(2, "URI support", "active"); +#ifdef URI_STATIC_BUILD + php_info_print_table_row(2, "uriparser bundled version", URI_VER_ANSI); +#else + php_info_print_table_row(2, "uriparser compiled version", URI_VER_ANSI); + php_info_print_table_row(2, "uriparser loaded version", uriBaseRuntimeVersionA()); +#endif php_info_print_table_end(); } static PHP_MSHUTDOWN_FUNCTION(uri) { - zend_hash_destroy(&uri_handlers); + zend_hash_destroy(&uri_parsers); return SUCCESS; } PHP_RINIT_FUNCTION(uri) { - if (lexbor_request_init() == FAILURE) { + if (PHP_RINIT(uri_parser_whatwg)(INIT_FUNC_ARGS_PASSTHRU) == FAILURE) { return FAILURE; } return SUCCESS; } -PHP_RSHUTDOWN_FUNCTION(uri) +ZEND_MODULE_POST_ZEND_DEACTIVATE_D(uri) { - lexbor_request_shutdown(); + if (ZEND_MODULE_POST_ZEND_DEACTIVATE_N(uri_parser_whatwg)() == FAILURE) { + return FAILURE; + } return SUCCESS; } @@ -687,8 +1173,10 @@ zend_module_entry uri_module_entry = { PHP_MINIT(uri), /* PHP_MINIT - Module initialization */ PHP_MSHUTDOWN(uri), /* PHP_MSHUTDOWN - Module shutdown */ PHP_RINIT(uri), /* PHP_RINIT - Request initialization */ - PHP_RSHUTDOWN(uri), /* PHP_RSHUTDOWN - Request shutdown */ + NULL, /* PHP_RSHUTDOWN - Request shutdown */ PHP_MINFO(uri), /* PHP_MINFO - Module info */ PHP_VERSION, /* Version */ - STANDARD_MODULE_PROPERTIES + NO_MODULE_GLOBALS, + ZEND_MODULE_POST_ZEND_DEACTIVATE_N(uri), + STANDARD_MODULE_PROPERTIES_EX }; diff --git a/ext/uri/php_uri.h b/ext/uri/php_uri.h index 9e22c227cbf83..97125f2b2700f 100644 --- a/ext/uri/php_uri.h +++ b/ext/uri/php_uri.h @@ -22,6 +22,191 @@ extern zend_module_entry uri_module_entry; #define phpext_uri_ptr &uri_module_entry -PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers); +typedef struct php_uri { + zend_string *scheme; + zend_string *user; + zend_string *password; + zend_string *host; + unsigned short port; + zend_string *path; + zend_string *query; + zend_string *fragment; +} php_uri; + +/** + * Registers a URI parser. The parser must have a unique name. + * + * @param uri_parser The URI parser + * @return SUCCESS in case of success, FAILURE otherwise + */ +PHPAPI zend_result php_uri_parser_register(const php_uri_parser *uri_parser); + +/** + * Returns the registered URI parser based on uri_parser_name. + * + * @param uri_parser_name The URI parser name + * @return The URI parser + */ +PHPAPI const php_uri_parser *php_uri_get_parser(zend_string *uri_parser_name); + +ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, bool silent); + +/** + * Retrieves the scheme component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Retrieves the username component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Retrieves the password component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Retrieves the host component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Retrieves the port component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_LONG or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Retrieves the path component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Retrieves the query component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Retrieves the fragment component based on the read_mode and passes it to the zv ZVAL in case of success. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param internal_uri The internal URI whose uri member is used to retrieve the component + * @param read_mode The read mode + * @param zv The output parameter containing the retrieved component as a ZVAL (either IS_STRING or IS_NULL). + * @return SUCCESS in case of success, FAILURE otherwise. + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv); + +/** + * Frees the uri member within the provided internal URI. + * + * @param internal_uri The internal URI + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(uri_internal_t *internal_uri); + +/** + * Creates a new php_uri struct containing all the URI components. The components are retrieved based on the read_mode parameter. + * + * Read_mode can be one of the following: + * - PHP_URI_COMPONENT_READ_MODE_RAW: Retrieves the raw, non-normalized variant of the URI component + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII: Retrieves the normalized variant of the requested URI component that must only contain ASCII characters + * - PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE: Retrieves the normalized variant of the requested URI component that may contain Unicode codepoints + * + * @param uri_parser The URI parser whose parse() handler is called + * @param uri_str The input string that is going to be parsed + * @param uri_str_len Length of the input string + * @param read_mode The read mode based on which components are retrieved + * @param silent Whether to throw a Uri\InvalidUriException in case of failure + * @return The created php_uri struct in case of success, NULL otherwise + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct( + const php_uri_parser *uri_parser, const char *uri_str, size_t uri_str_len, php_uri_component_read_mode read_mode, bool silent +); + +/** + * Frees the provided php_uri struct. + * + * @param uri The php_uri struct to free + */ +ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_struct_free(php_uri *uri); + +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( + INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const zend_object *base_url_object, + bool should_throw, bool should_update_this_object, zval *errors_zv +); #endif diff --git a/ext/uri/php_uri.stub.php b/ext/uri/php_uri.stub.php index ef49e4ba6f968..b4063bee8f596 100644 --- a/ext/uri/php_uri.stub.php +++ b/ext/uri/php_uri.stub.php @@ -20,6 +20,78 @@ enum UriComparisonMode } } +namespace Uri\Rfc3986 { + /** @strict-properties */ + final readonly class Uri + { + public static function parse(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null): ?static {} + + public function __construct(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null) {} + + public function getScheme(): ?string {} + + public function getRawScheme(): ?string {} + + public function withScheme(?string $scheme): static {} + + public function getUserInfo(): ?string {} + + public function getRawUserInfo(): ?string {} + + public function withUserInfo(#[\SensitiveParameter] ?string $userinfo): static {} + + public function getUsername(): ?string {} + + public function getRawUsername(): ?string {} + + public function getPassword(): ?string {} + + public function getRawPassword(): ?string {} + + public function getHost(): ?string {} + + public function getRawHost(): ?string {} + + public function withHost(?string $host): static {} + + public function getPort(): ?int {} + + public function withPort(?int $port): static {} + + public function getPath(): string {} + + public function getRawPath(): string {} + + public function withPath(string $path): static {} + + public function getQuery(): ?string {} + + public function getRawQuery(): ?string {} + + public function withQuery(?string $query): static {} + + public function getFragment(): ?string {} + + public function getRawFragment(): ?string {} + + public function withFragment(?string $fragment): static {} + + public function equals(\Uri\Rfc3986\Uri $uri, \Uri\UriComparisonMode $comparisonMode = \Uri\UriComparisonMode::ExcludeFragment): bool {} + + public function toString(): string {} + + public function toRawString(): string {} + + public function resolve(string $uri): static {} + + public function __serialize(): array {} + + public function __unserialize(array $data): void {} + + public function __debugInfo(): array {} + } +} + namespace Uri\WhatWg { /** @strict-properties */ class InvalidUrlException extends \Uri\InvalidUriException @@ -85,10 +157,12 @@ public function getScheme(): string {} public function withScheme(string $scheme): static {} + /** @implementation-alias Uri\Rfc3986\Uri::getUsername */ public function getUsername(): ?string {} public function withUsername(?string $username): static {} + /** @implementation-alias Uri\Rfc3986\Uri::getPassword */ public function getPassword(): ?string {} public function withPassword(#[\SensitiveParameter] ?string $password): static {} @@ -97,22 +171,31 @@ public function getAsciiHost(): ?string {} public function getUnicodeHost(): ?string {} + /** @implementation-alias Uri\Rfc3986\Uri::withHost */ public function withHost(?string $host): static {} + /** @implementation-alias Uri\Rfc3986\Uri::getPort */ public function getPort(): ?int {} + /** @implementation-alias Uri\Rfc3986\Uri::withPort */ public function withPort(?int $port): static {} + /** @implementation-alias Uri\Rfc3986\Uri::getPath */ public function getPath(): string {} + /** @implementation-alias Uri\Rfc3986\Uri::withPath */ public function withPath(string $path): static {} + /** @implementation-alias Uri\Rfc3986\Uri::getQuery */ public function getQuery(): ?string {} + /** @implementation-alias Uri\Rfc3986\Uri::withQuery */ public function withQuery(?string $query): static {} + /** @implementation-alias Uri\Rfc3986\Uri::getFragment */ public function getFragment(): ?string {} + /** @implementation-alias Uri\Rfc3986\Uri::withFragment */ public function withFragment(?string $fragment): static {} public function equals(\Uri\WhatWg\Url $url, \Uri\UriComparisonMode $comparisonMode = \Uri\UriComparisonMode::ExcludeFragment): bool {} diff --git a/ext/uri/php_uri_arginfo.h b/ext/uri/php_uri_arginfo.h index 0ae755a9f70dc..12a498357ea28 100644 --- a/ext/uri/php_uri_arginfo.h +++ b/ext/uri/php_uri_arginfo.h @@ -1,5 +1,102 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 1945c28deef13c2af552b18c2a5a6c7798d4aeec */ + * Stub hash: bf37e0babfcc453ab0c75d0e87e142dfa3b5e61e */ + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_parse, 0, 1, IS_STATIC, 1) + ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0) + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, baseUrl, Uri\\Rfc3986\\\125ri, 1, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Uri_Rfc3986_Uri___construct, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0) + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, baseUrl, Uri\\Rfc3986\\\125ri, 1, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getScheme, 0, 0, IS_STRING, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri_getRawScheme arginfo_class_Uri_Rfc3986_Uri_getScheme + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withScheme, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, scheme, IS_STRING, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri_getUserInfo arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getRawUserInfo arginfo_class_Uri_Rfc3986_Uri_getScheme + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withUserInfo, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, userinfo, IS_STRING, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri_getUsername arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getRawUsername arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getPassword arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getRawPassword arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getHost arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getRawHost arginfo_class_Uri_Rfc3986_Uri_getScheme + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withHost, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getPort, 0, 0, IS_LONG, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withPort, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_getPath, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri_getRawPath arginfo_class_Uri_Rfc3986_Uri_getPath + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withPath, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri_getQuery arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getRawQuery arginfo_class_Uri_Rfc3986_Uri_getScheme + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withQuery, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri_getFragment arginfo_class_Uri_Rfc3986_Uri_getScheme + +#define arginfo_class_Uri_Rfc3986_Uri_getRawFragment arginfo_class_Uri_Rfc3986_Uri_getScheme + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_withFragment, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, fragment, IS_STRING, 1) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_equals, 0, 1, _IS_BOOL, 0) + ZEND_ARG_OBJ_INFO(0, uri, Uri\\Rfc3986\\\125ri, 0) + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, comparisonMode, Uri\\\125riComparisonMode, 0, "Uri\\UriComparisonMode::ExcludeFragment") +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri_toString arginfo_class_Uri_Rfc3986_Uri_getPath + +#define arginfo_class_Uri_Rfc3986_Uri_toRawString arginfo_class_Uri_Rfc3986_Uri_getPath + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri_resolve, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri___serialize, 0, 0, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_Rfc3986_Uri___unserialize, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Uri_Rfc3986_Uri___debugInfo arginfo_class_Uri_Rfc3986_Uri___serialize ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Uri_WhatWg_InvalidUrlException___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, message, IS_STRING, 0, "\"\"") @@ -26,103 +123,109 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Uri_WhatWg_Url___construct, 0, 0, 1) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, softErrors, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_getScheme, 0, 0, IS_STRING, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_getScheme arginfo_class_Uri_Rfc3986_Uri_getPath ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withScheme, 0, 1, IS_STATIC, 0) ZEND_ARG_TYPE_INFO(0, scheme, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_getUsername, 0, 0, IS_STRING, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_getUsername arginfo_class_Uri_Rfc3986_Uri_getScheme ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withUsername, 0, 1, IS_STATIC, 0) ZEND_ARG_TYPE_INFO(0, username, IS_STRING, 1) ZEND_END_ARG_INFO() -#define arginfo_class_Uri_WhatWg_Url_getPassword arginfo_class_Uri_WhatWg_Url_getUsername +#define arginfo_class_Uri_WhatWg_Url_getPassword arginfo_class_Uri_Rfc3986_Uri_getScheme ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPassword, 0, 1, IS_STATIC, 0) ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 1) ZEND_END_ARG_INFO() -#define arginfo_class_Uri_WhatWg_Url_getAsciiHost arginfo_class_Uri_WhatWg_Url_getUsername +#define arginfo_class_Uri_WhatWg_Url_getAsciiHost arginfo_class_Uri_Rfc3986_Uri_getScheme -#define arginfo_class_Uri_WhatWg_Url_getUnicodeHost arginfo_class_Uri_WhatWg_Url_getUsername +#define arginfo_class_Uri_WhatWg_Url_getUnicodeHost arginfo_class_Uri_Rfc3986_Uri_getScheme -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withHost, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withHost arginfo_class_Uri_Rfc3986_Uri_withHost -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_getPort, 0, 0, IS_LONG, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_getPort arginfo_class_Uri_Rfc3986_Uri_getPort -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPort, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withPort arginfo_class_Uri_Rfc3986_Uri_withPort -#define arginfo_class_Uri_WhatWg_Url_getPath arginfo_class_Uri_WhatWg_Url_getScheme +#define arginfo_class_Uri_WhatWg_Url_getPath arginfo_class_Uri_Rfc3986_Uri_getPath -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withPath, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withPath arginfo_class_Uri_Rfc3986_Uri_withPath -#define arginfo_class_Uri_WhatWg_Url_getQuery arginfo_class_Uri_WhatWg_Url_getUsername +#define arginfo_class_Uri_WhatWg_Url_getQuery arginfo_class_Uri_Rfc3986_Uri_getScheme -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withQuery, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withQuery arginfo_class_Uri_Rfc3986_Uri_withQuery -#define arginfo_class_Uri_WhatWg_Url_getFragment arginfo_class_Uri_WhatWg_Url_getUsername +#define arginfo_class_Uri_WhatWg_Url_getFragment arginfo_class_Uri_Rfc3986_Uri_getScheme -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_withFragment, 0, 1, IS_STATIC, 0) - ZEND_ARG_TYPE_INFO(0, fragment, IS_STRING, 1) -ZEND_END_ARG_INFO() +#define arginfo_class_Uri_WhatWg_Url_withFragment arginfo_class_Uri_Rfc3986_Uri_withFragment ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_equals, 0, 1, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, url, Uri\\WhatWg\\\125rl, 0) ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, comparisonMode, Uri\\\125riComparisonMode, 0, "Uri\\UriComparisonMode::ExcludeFragment") ZEND_END_ARG_INFO() -#define arginfo_class_Uri_WhatWg_Url_toAsciiString arginfo_class_Uri_WhatWg_Url_getScheme +#define arginfo_class_Uri_WhatWg_Url_toAsciiString arginfo_class_Uri_Rfc3986_Uri_getPath -#define arginfo_class_Uri_WhatWg_Url_toUnicodeString arginfo_class_Uri_WhatWg_Url_getScheme +#define arginfo_class_Uri_WhatWg_Url_toUnicodeString arginfo_class_Uri_Rfc3986_Uri_getPath ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url_resolve, 0, 1, IS_STATIC, 0) ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, softErrors, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url___serialize, 0, 0, IS_ARRAY, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Uri_WhatWg_Url___unserialize, 0, 1, IS_VOID, 0) - ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) -ZEND_END_ARG_INFO() - -#define arginfo_class_Uri_WhatWg_Url___debugInfo arginfo_class_Uri_WhatWg_Url___serialize - +#define arginfo_class_Uri_WhatWg_Url___serialize arginfo_class_Uri_Rfc3986_Uri___serialize + +#define arginfo_class_Uri_WhatWg_Url___unserialize arginfo_class_Uri_Rfc3986_Uri___unserialize + +#define arginfo_class_Uri_WhatWg_Url___debugInfo arginfo_class_Uri_Rfc3986_Uri___serialize + +ZEND_METHOD(Uri_Rfc3986_Uri, parse); +ZEND_METHOD(Uri_Rfc3986_Uri, __construct); +ZEND_METHOD(Uri_Rfc3986_Uri, getScheme); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawScheme); +ZEND_METHOD(Uri_Rfc3986_Uri, withScheme); +ZEND_METHOD(Uri_Rfc3986_Uri, getUserInfo); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawUserInfo); +ZEND_METHOD(Uri_Rfc3986_Uri, withUserInfo); +ZEND_METHOD(Uri_Rfc3986_Uri, getUsername); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawUsername); +ZEND_METHOD(Uri_Rfc3986_Uri, getPassword); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawPassword); +ZEND_METHOD(Uri_Rfc3986_Uri, getHost); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawHost); +ZEND_METHOD(Uri_Rfc3986_Uri, withHost); +ZEND_METHOD(Uri_Rfc3986_Uri, getPort); +ZEND_METHOD(Uri_Rfc3986_Uri, withPort); +ZEND_METHOD(Uri_Rfc3986_Uri, getPath); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawPath); +ZEND_METHOD(Uri_Rfc3986_Uri, withPath); +ZEND_METHOD(Uri_Rfc3986_Uri, getQuery); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawQuery); +ZEND_METHOD(Uri_Rfc3986_Uri, withQuery); +ZEND_METHOD(Uri_Rfc3986_Uri, getFragment); +ZEND_METHOD(Uri_Rfc3986_Uri, getRawFragment); +ZEND_METHOD(Uri_Rfc3986_Uri, withFragment); +ZEND_METHOD(Uri_Rfc3986_Uri, equals); +ZEND_METHOD(Uri_Rfc3986_Uri, toString); +ZEND_METHOD(Uri_Rfc3986_Uri, toRawString); +ZEND_METHOD(Uri_Rfc3986_Uri, resolve); +ZEND_METHOD(Uri_Rfc3986_Uri, __serialize); +ZEND_METHOD(Uri_Rfc3986_Uri, __unserialize); +ZEND_METHOD(Uri_Rfc3986_Uri, __debugInfo); ZEND_METHOD(Uri_WhatWg_InvalidUrlException, __construct); ZEND_METHOD(Uri_WhatWg_UrlValidationError, __construct); ZEND_METHOD(Uri_WhatWg_Url, parse); ZEND_METHOD(Uri_WhatWg_Url, __construct); ZEND_METHOD(Uri_WhatWg_Url, getScheme); ZEND_METHOD(Uri_WhatWg_Url, withScheme); -ZEND_METHOD(Uri_WhatWg_Url, getUsername); ZEND_METHOD(Uri_WhatWg_Url, withUsername); -ZEND_METHOD(Uri_WhatWg_Url, getPassword); ZEND_METHOD(Uri_WhatWg_Url, withPassword); ZEND_METHOD(Uri_WhatWg_Url, getAsciiHost); ZEND_METHOD(Uri_WhatWg_Url, getUnicodeHost); -ZEND_METHOD(Uri_WhatWg_Url, withHost); -ZEND_METHOD(Uri_WhatWg_Url, getPort); -ZEND_METHOD(Uri_WhatWg_Url, withPort); -ZEND_METHOD(Uri_WhatWg_Url, getPath); -ZEND_METHOD(Uri_WhatWg_Url, withPath); -ZEND_METHOD(Uri_WhatWg_Url, getQuery); -ZEND_METHOD(Uri_WhatWg_Url, withQuery); -ZEND_METHOD(Uri_WhatWg_Url, getFragment); -ZEND_METHOD(Uri_WhatWg_Url, withFragment); ZEND_METHOD(Uri_WhatWg_Url, equals); ZEND_METHOD(Uri_WhatWg_Url, toAsciiString); ZEND_METHOD(Uri_WhatWg_Url, toUnicodeString); @@ -131,6 +234,43 @@ ZEND_METHOD(Uri_WhatWg_Url, __serialize); ZEND_METHOD(Uri_WhatWg_Url, __unserialize); ZEND_METHOD(Uri_WhatWg_Url, __debugInfo); +static const zend_function_entry class_Uri_Rfc3986_Uri_methods[] = { + ZEND_ME(Uri_Rfc3986_Uri, parse, arginfo_class_Uri_Rfc3986_Uri_parse, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(Uri_Rfc3986_Uri, __construct, arginfo_class_Uri_Rfc3986_Uri___construct, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getScheme, arginfo_class_Uri_Rfc3986_Uri_getScheme, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawScheme, arginfo_class_Uri_Rfc3986_Uri_getRawScheme, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withScheme, arginfo_class_Uri_Rfc3986_Uri_withScheme, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getUserInfo, arginfo_class_Uri_Rfc3986_Uri_getUserInfo, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawUserInfo, arginfo_class_Uri_Rfc3986_Uri_getRawUserInfo, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withUserInfo, arginfo_class_Uri_Rfc3986_Uri_withUserInfo, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getUsername, arginfo_class_Uri_Rfc3986_Uri_getUsername, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawUsername, arginfo_class_Uri_Rfc3986_Uri_getRawUsername, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getPassword, arginfo_class_Uri_Rfc3986_Uri_getPassword, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawPassword, arginfo_class_Uri_Rfc3986_Uri_getRawPassword, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getHost, arginfo_class_Uri_Rfc3986_Uri_getHost, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawHost, arginfo_class_Uri_Rfc3986_Uri_getRawHost, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withHost, arginfo_class_Uri_Rfc3986_Uri_withHost, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getPort, arginfo_class_Uri_Rfc3986_Uri_getPort, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withPort, arginfo_class_Uri_Rfc3986_Uri_withPort, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getPath, arginfo_class_Uri_Rfc3986_Uri_getPath, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawPath, arginfo_class_Uri_Rfc3986_Uri_getRawPath, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withPath, arginfo_class_Uri_Rfc3986_Uri_withPath, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getQuery, arginfo_class_Uri_Rfc3986_Uri_getQuery, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawQuery, arginfo_class_Uri_Rfc3986_Uri_getRawQuery, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withQuery, arginfo_class_Uri_Rfc3986_Uri_withQuery, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getFragment, arginfo_class_Uri_Rfc3986_Uri_getFragment, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, getRawFragment, arginfo_class_Uri_Rfc3986_Uri_getRawFragment, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, withFragment, arginfo_class_Uri_Rfc3986_Uri_withFragment, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, equals, arginfo_class_Uri_Rfc3986_Uri_equals, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, toString, arginfo_class_Uri_Rfc3986_Uri_toString, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, toRawString, arginfo_class_Uri_Rfc3986_Uri_toRawString, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, resolve, arginfo_class_Uri_Rfc3986_Uri_resolve, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, __serialize, arginfo_class_Uri_Rfc3986_Uri___serialize, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, __unserialize, arginfo_class_Uri_Rfc3986_Uri___unserialize, ZEND_ACC_PUBLIC) + ZEND_ME(Uri_Rfc3986_Uri, __debugInfo, arginfo_class_Uri_Rfc3986_Uri___debugInfo, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + static const zend_function_entry class_Uri_WhatWg_InvalidUrlException_methods[] = { ZEND_ME(Uri_WhatWg_InvalidUrlException, __construct, arginfo_class_Uri_WhatWg_InvalidUrlException___construct, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -146,21 +286,21 @@ static const zend_function_entry class_Uri_WhatWg_Url_methods[] = { ZEND_ME(Uri_WhatWg_Url, __construct, arginfo_class_Uri_WhatWg_Url___construct, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, getScheme, arginfo_class_Uri_WhatWg_Url_getScheme, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, withScheme, arginfo_class_Uri_WhatWg_Url_withScheme, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, getUsername, arginfo_class_Uri_WhatWg_Url_getUsername, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("getUsername", zim_Uri_Rfc3986_Uri_getUsername, arginfo_class_Uri_WhatWg_Url_getUsername, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(Uri_WhatWg_Url, withUsername, arginfo_class_Uri_WhatWg_Url_withUsername, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, getPassword, arginfo_class_Uri_WhatWg_Url_getPassword, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("getPassword", zim_Uri_Rfc3986_Uri_getPassword, arginfo_class_Uri_WhatWg_Url_getPassword, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(Uri_WhatWg_Url, withPassword, arginfo_class_Uri_WhatWg_Url_withPassword, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, getAsciiHost, arginfo_class_Uri_WhatWg_Url_getAsciiHost, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, getUnicodeHost, arginfo_class_Uri_WhatWg_Url_getUnicodeHost, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, withHost, arginfo_class_Uri_WhatWg_Url_withHost, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, getPort, arginfo_class_Uri_WhatWg_Url_getPort, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, withPort, arginfo_class_Uri_WhatWg_Url_withPort, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, getPath, arginfo_class_Uri_WhatWg_Url_getPath, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, withPath, arginfo_class_Uri_WhatWg_Url_withPath, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, getQuery, arginfo_class_Uri_WhatWg_Url_getQuery, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, withQuery, arginfo_class_Uri_WhatWg_Url_withQuery, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, getFragment, arginfo_class_Uri_WhatWg_Url_getFragment, ZEND_ACC_PUBLIC) - ZEND_ME(Uri_WhatWg_Url, withFragment, arginfo_class_Uri_WhatWg_Url_withFragment, ZEND_ACC_PUBLIC) + ZEND_RAW_FENTRY("withHost", zim_Uri_Rfc3986_Uri_withHost, arginfo_class_Uri_WhatWg_Url_withHost, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("getPort", zim_Uri_Rfc3986_Uri_getPort, arginfo_class_Uri_WhatWg_Url_getPort, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("withPort", zim_Uri_Rfc3986_Uri_withPort, arginfo_class_Uri_WhatWg_Url_withPort, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("getPath", zim_Uri_Rfc3986_Uri_getPath, arginfo_class_Uri_WhatWg_Url_getPath, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("withPath", zim_Uri_Rfc3986_Uri_withPath, arginfo_class_Uri_WhatWg_Url_withPath, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("getQuery", zim_Uri_Rfc3986_Uri_getQuery, arginfo_class_Uri_WhatWg_Url_getQuery, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("withQuery", zim_Uri_Rfc3986_Uri_withQuery, arginfo_class_Uri_WhatWg_Url_withQuery, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("getFragment", zim_Uri_Rfc3986_Uri_getFragment, arginfo_class_Uri_WhatWg_Url_getFragment, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("withFragment", zim_Uri_Rfc3986_Uri_withFragment, arginfo_class_Uri_WhatWg_Url_withFragment, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_ME(Uri_WhatWg_Url, equals, arginfo_class_Uri_WhatWg_Url_equals, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, toAsciiString, arginfo_class_Uri_WhatWg_Url_toAsciiString, ZEND_ACC_PUBLIC) ZEND_ME(Uri_WhatWg_Url, toUnicodeString, arginfo_class_Uri_WhatWg_Url_toUnicodeString, ZEND_ACC_PUBLIC) @@ -202,6 +342,19 @@ static zend_class_entry *register_class_Uri_UriComparisonMode(void) return class_entry; } +static zend_class_entry *register_class_Uri_Rfc3986_Uri(void) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "Uri\\Rfc3986", "Uri", class_Uri_Rfc3986_Uri_methods); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_READONLY_CLASS); + + + zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "withuserinfo", sizeof("withuserinfo") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); + + return class_entry; +} + static zend_class_entry *register_class_Uri_WhatWg_InvalidUrlException(zend_class_entry *class_entry_Uri_InvalidUriException) { zend_class_entry ce, *class_entry; diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index 9128b942e57b8..efb7688a94502 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -19,105 +19,80 @@ #include "Zend/zend_exceptions.h" #include "php_uri_common.h" -const uri_property_handler_t *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, uri_property_name_t property_name) +static zend_string *get_known_string_by_property_name(php_uri_property_name property_name) { switch (property_name) { - case URI_PROPERTY_NAME_SCHEME: - return &internal_uri->handler->property_handlers.scheme; - case URI_PROPERTY_NAME_USERNAME: - return &internal_uri->handler->property_handlers.username; - case URI_PROPERTY_NAME_PASSWORD: - return &internal_uri->handler->property_handlers.password; - case URI_PROPERTY_NAME_HOST: - return &internal_uri->handler->property_handlers.host; - case URI_PROPERTY_NAME_PORT: - return &internal_uri->handler->property_handlers.port; - case URI_PROPERTY_NAME_PATH: - return &internal_uri->handler->property_handlers.path; - case URI_PROPERTY_NAME_QUERY: - return &internal_uri->handler->property_handlers.query; - case URI_PROPERTY_NAME_FRAGMENT: - return &internal_uri->handler->property_handlers.fragment; - EMPTY_SWITCH_DEFAULT_CASE() - } -} - -static zend_string *get_known_string_by_property_name(uri_property_name_t property_name) -{ - switch (property_name) { - case URI_PROPERTY_NAME_SCHEME: + case PHP_URI_PROPERTY_NAME_SCHEME: return ZSTR_KNOWN(ZEND_STR_SCHEME); - case URI_PROPERTY_NAME_USERNAME: + case PHP_URI_PROPERTY_NAME_USERNAME: return ZSTR_KNOWN(ZEND_STR_USERNAME); - case URI_PROPERTY_NAME_PASSWORD: + case PHP_URI_PROPERTY_NAME_PASSWORD: return ZSTR_KNOWN(ZEND_STR_PASSWORD); - case URI_PROPERTY_NAME_HOST: + case PHP_URI_PROPERTY_NAME_HOST: return ZSTR_KNOWN(ZEND_STR_HOST); - case URI_PROPERTY_NAME_PORT: + case PHP_URI_PROPERTY_NAME_PORT: return ZSTR_KNOWN(ZEND_STR_PORT); - case URI_PROPERTY_NAME_PATH: + case PHP_URI_PROPERTY_NAME_PATH: return ZSTR_KNOWN(ZEND_STR_PATH); - case URI_PROPERTY_NAME_QUERY: + case PHP_URI_PROPERTY_NAME_QUERY: return ZSTR_KNOWN(ZEND_STR_QUERY); - case URI_PROPERTY_NAME_FRAGMENT: + case PHP_URI_PROPERTY_NAME_FRAGMENT: return ZSTR_KNOWN(ZEND_STR_FRAGMENT); EMPTY_SWITCH_DEFAULT_CASE() } } -void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name, uri_component_read_mode_t component_read_mode) +void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, php_uri_component_read_mode component_read_mode) { ZEND_PARSE_PARAMETERS_NONE(); uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); URI_ASSERT_INITIALIZATION(internal_uri); - const uri_property_handler_t *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - ZEND_ASSERT(property_handler != NULL); + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); - if (UNEXPECTED(property_handler->read_func(internal_uri, component_read_mode, return_value) == FAILURE)) { - zend_throw_error(NULL, "%s::$%s property cannot be retrieved", ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name), - ZSTR_VAL(get_known_string_by_property_name(property_name))); + if (UNEXPECTED(property_handler->read(internal_uri->uri, component_read_mode, return_value) == FAILURE)) { + zend_throw_error(NULL, "The %s component cannot be retrieved", ZSTR_VAL(get_known_string_by_property_name(property_name))); RETURN_THROWS(); } } -static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name, zval *property_zv) +static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, zval *property_zv) { + zend_object *old_object = Z_OBJ_P(ZEND_THIS); uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); URI_ASSERT_INITIALIZATION(internal_uri); - const uri_property_handler_t *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - ZEND_ASSERT(property_handler != NULL); - - zend_object *new_object = uri_clone_obj_handler(Z_OBJ_P(ZEND_THIS)); - if (UNEXPECTED(EG(exception) != NULL)) { - zend_object_release(new_object); + zend_object *new_object = old_object->handlers->clone_obj(old_object); + if (new_object == NULL) { RETURN_THROWS(); } + /* Assign the object early. The engine will take care of destruction in + * case of an exception being thrown. */ + RETVAL_OBJ(new_object); + + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); + uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); URI_ASSERT_INITIALIZATION(new_internal_uri); - if (property_handler->write_func == NULL) { - zend_readonly_property_modification_error_ex(ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name), + if (UNEXPECTED(property_handler->write == NULL)) { + zend_readonly_property_modification_error_ex(ZSTR_VAL(old_object->ce->name), ZSTR_VAL(get_known_string_by_property_name(property_name))); - zend_object_release(new_object); RETURN_THROWS(); } zval errors; ZVAL_UNDEF(&errors); - if (property_handler->write_func(new_internal_uri, property_zv, &errors) == FAILURE) { + if (UNEXPECTED(property_handler->write(new_internal_uri->uri, property_zv, &errors) == FAILURE)) { zval_ptr_dtor(&errors); - zend_object_release(new_object); RETURN_THROWS(); } ZEND_ASSERT(Z_ISUNDEF(errors)); - RETVAL_OBJ(new_object); } -void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name) +void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name) { zend_string *value; @@ -131,7 +106,7 @@ void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t p uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); } -void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name) +void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name) { zend_string *value; @@ -149,7 +124,7 @@ void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_ uri_write_component_ex(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_name, &zv); } -void uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name) +void uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name) { zend_long value; bool value_is_null; diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index 1aee1cd512472..f061db6f981b1 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -17,6 +17,8 @@ #ifndef PHP_URI_COMMON_H #define PHP_URI_COMMON_H +extern zend_class_entry *uri_rfc3986_uri_ce; +extern zend_object_handlers uri_rfc3986_uri_object_handlers; extern zend_class_entry *uri_whatwg_url_ce; extern zend_object_handlers uri_whatwg_uri_object_handlers; extern zend_class_entry *uri_comparison_mode_ce; @@ -25,59 +27,48 @@ extern zend_class_entry *uri_invalid_uri_exception_ce; extern zend_class_entry *uri_whatwg_invalid_url_exception_ce; extern zend_class_entry *uri_whatwg_url_validation_error_type_ce; extern zend_class_entry *uri_whatwg_url_validation_error_ce; -extern zend_object *uri_clone_obj_handler(zend_object *object); - -typedef enum { - URI_RECOMPOSITION_RAW_ASCII, - URI_RECOMPOSITION_RAW_UNICODE, - URI_RECOMPOSITION_NORMALIZED_ASCII, - URI_RECOMPOSITION_NORMALIZED_UNICODE, -} uri_recomposition_mode_t; - -typedef enum { - URI_COMPONENT_READ_RAW, - URI_COMPONENT_READ_NORMALIZED_ASCII, - URI_COMPONENT_READ_NORMALIZED_UNICODE, -} uri_component_read_mode_t; - -struct uri_internal_t; - -typedef zend_result (*uri_read_t)(const struct uri_internal_t *internal_uri, uri_component_read_mode_t read_mode, zval *retval); - -typedef zend_result (*uri_write_t)(struct uri_internal_t *internal_uri, zval *value, zval *errors); - -typedef enum { - URI_PROPERTY_NAME_SCHEME, - URI_PROPERTY_NAME_USERNAME, - URI_PROPERTY_NAME_PASSWORD, - URI_PROPERTY_NAME_HOST, - URI_PROPERTY_NAME_PORT, - URI_PROPERTY_NAME_PATH, - URI_PROPERTY_NAME_QUERY, - URI_PROPERTY_NAME_FRAGMENT, -} uri_property_name_t; - -typedef struct uri_property_handler_t { - uri_read_t read_func; - uri_write_t write_func; -} uri_property_handler_t; - -typedef struct uri_property_handlers_t { - uri_property_handler_t scheme; - uri_property_handler_t username; - uri_property_handler_t password; - uri_property_handler_t host; - uri_property_handler_t port; - uri_property_handler_t path; - uri_property_handler_t query; - uri_property_handler_t fragment; -} uri_property_handlers_t; - -typedef struct uri_handler_t { + +typedef enum php_uri_recomposition_mode { + PHP_URI_RECOMPOSITION_MODE_RAW_ASCII, + PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE, + PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII, + PHP_URI_RECOMPOSITION_MODE_NORMALIZED_UNICODE, +} php_uri_recomposition_mode; + +typedef enum php_uri_component_read_mode { + PHP_URI_COMPONENT_READ_MODE_RAW, + PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, + PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE, +} php_uri_component_read_mode; + +typedef zend_result (*php_uri_property_handler_read)(void *uri, php_uri_component_read_mode read_mode, zval *retval); + +typedef zend_result (*php_uri_property_handler_write)(void *uri, zval *value, zval *errors); + +typedef enum php_uri_property_name { + PHP_URI_PROPERTY_NAME_SCHEME, + PHP_URI_PROPERTY_NAME_USERNAME, + PHP_URI_PROPERTY_NAME_PASSWORD, + PHP_URI_PROPERTY_NAME_HOST, + PHP_URI_PROPERTY_NAME_PORT, + PHP_URI_PROPERTY_NAME_PATH, + PHP_URI_PROPERTY_NAME_QUERY, + PHP_URI_PROPERTY_NAME_FRAGMENT, +} php_uri_property_name; + +typedef struct php_uri_property_handler { + php_uri_property_handler_read read; + php_uri_property_handler_write write; +} php_uri_property_handler; + +typedef struct php_uri_parser { + /** + * Name (the FQCN) of the URI parser. The "" name is reserved for the handler of the legacy parse_url(). + */ const char *name; /** - * Parse a URI string into a URI. + * Parses a URI string into a URI. * * If the URI string is valid, a URI is returned. In case of failure, NULL is * returned. @@ -91,17 +82,62 @@ typedef struct uri_handler_t { * * If the silent parameter is true, a Uri\InvalidUriException instance must be thrown. * If the parameter is false, the possible errors should be handled by the caller. + * + * @param uri_str The input string that is going to be parsed + * @param uri_str_len Length of the input string + * @param base_url The base URI if reference resolution should be performed, otherwise NULL + * @param errors An out parameter that stores additional error information + * @param silent Whether to throw a Uri\InvalidUriException in case of failure */ - void *(*parse_uri)(const zend_string *uri_str, const void *base_url, zval *errors, bool silent); - void *(*clone_uri)(void *uri); - zend_string *(*uri_to_string)(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment); - void (*free_uri)(void *uri); + void *(*parse)(const char *uri_str, size_t uri_str_len, const void *base_url, zval *errors, bool silent); - const uri_property_handlers_t property_handlers; -} uri_handler_t; + /** + * Clones a URI to a new URI. + * + * A deep-clone must be performed that copies all pointer members to a new memory address. + * @param uri The input URI + * @return The cloned URI + */ + void *(*clone)(void *uri); + + /** + * Recomposes a URI as a string according to the recomposition_mode and exclude_fragment parameters. + * The returned zend_string must not be persistent. + * + * Recomposition_mode can be one of the following: + * - PHP_URI_RECOMPOSITION_MODE_RAW_ASCII: Recomposes the raw, non-normalized variant of the URI as a string that must only contain ASCII characters + * - PHP_URI_RECOMPOSITION_MODE_RAW_UNICODE: Recomposes the raw, non-normalized variant of the URI as a string that may contain Unicode codepoints + * - PHP_URI_RECOMPOSITION_MODE_NORMALIZED_ASCII: Recomposes the normalized variant of the URI as a string that must only contain ASCII characters + * - PHP_URI_RECOMPOSITION_MODE_NORMALIZED_UNICODE: Recomposes the normalized variant of the URI as a string that may contain Unicode codepoints + * + * @param uri The input URI + * @param recomposition_mode The type of recomposition + * @param exclude_fragment Whether the fragment component should be part of the recomposed URI + * @return The recomposed URI as a non-persistent zend_string + */ + zend_string *(*to_string)(void *uri, php_uri_recomposition_mode recomposition_mode, bool exclude_fragment); + + /** + * Frees the provided URI. + * + * @param uri The URI to free. Must do nothing if NULL. + */ + void (*free)(void *uri); + + struct { + php_uri_property_handler scheme; + php_uri_property_handler username; + php_uri_property_handler password; + php_uri_property_handler host; + php_uri_property_handler port; + php_uri_property_handler path; + php_uri_property_handler query; + php_uri_property_handler fragment; + } property_handler; +} php_uri_parser; typedef struct uri_internal_t { - const uri_handler_t *handler; + const php_uri_parser *parser; void *uri; } uri_internal_t; @@ -121,15 +157,42 @@ static inline uri_internal_t *uri_internal_from_obj(const zend_object *object) { #define Z_URI_OBJECT_P(zv) uri_object_from_obj(Z_OBJ_P((zv))) #define Z_URI_INTERNAL_P(zv) uri_internal_from_obj(Z_OBJ_P((zv))) -#define URI_PARSER_WHATWG "Uri\\WhatWg\\Url" +PHPAPI uri_object_t *php_uri_object_create(zend_class_entry *class_type, const php_uri_parser *parser); +PHPAPI void php_uri_object_handler_free(zend_object *object); +PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object); + +#define PHP_URI_PARSER_RFC3986 "Uri\\Rfc3986\\Uri" +#define PHP_URI_PARSER_WHATWG "Uri\\WhatWg\\Url" +#define PHP_URI_PARSER_PHP_PARSE_URL "parse_url" #define URI_SERIALIZED_PROPERTY_NAME "uri" -zend_result uri_handler_register(const uri_handler_t *uri_handler); -const uri_property_handler_t *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, uri_property_name_t property_name); -void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name, uri_component_read_mode_t component_read_mode); -void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name); -void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name); -void uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name); +static inline const php_uri_property_handler *php_uri_parser_property_handler_by_name(const php_uri_parser *parser, php_uri_property_name property_name) +{ + switch (property_name) { + case PHP_URI_PROPERTY_NAME_SCHEME: + return &parser->property_handler.scheme; + case PHP_URI_PROPERTY_NAME_USERNAME: + return &parser->property_handler.username; + case PHP_URI_PROPERTY_NAME_PASSWORD: + return &parser->property_handler.password; + case PHP_URI_PROPERTY_NAME_HOST: + return &parser->property_handler.host; + case PHP_URI_PROPERTY_NAME_PORT: + return &parser->property_handler.port; + case PHP_URI_PROPERTY_NAME_PATH: + return &parser->property_handler.path; + case PHP_URI_PROPERTY_NAME_QUERY: + return &parser->property_handler.query; + case PHP_URI_PROPERTY_NAME_FRAGMENT: + return &parser->property_handler.fragment; + EMPTY_SWITCH_DEFAULT_CASE() + } +} + +void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, php_uri_component_read_mode component_read_mode); +void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); +void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); +void uri_write_component_long_or_null(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); #define URI_ASSERT_INITIALIZATION(internal_uri) do { \ ZEND_ASSERT(internal_uri != NULL && internal_uri->uri != NULL); \ diff --git a/ext/uri/tests/003.phpt b/ext/uri/tests/003.phpt index bcd6e417441c2..a1918f7a838b2 100644 --- a/ext/uri/tests/003.phpt +++ b/ext/uri/tests/003.phpt @@ -1,16 +1,21 @@ --TEST-- -Parse URL exotic URLs +Parse special URIs --EXTENSIONS-- uri --FILE-- --EXPECTF-- +NULL object(Uri\WhatWg\Url)#%d (%d) { ["scheme"]=> string(4) "http" @@ -29,4 +34,58 @@ object(Uri\WhatWg\Url)#%d (%d) { ["fragment"]=> string(6) "anchor" } +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(7) "host123" + ["port"]=> + NULL + ["path"]=> + string(1) "/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(0) "" + ["port"]=> + NULL + ["path"]=> + string(5) "/foo/" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(7) "/page:1" + ["query"]=> + NULL + ["fragment"]=> + NULL +} NULL diff --git a/ext/uri/tests/004.phpt b/ext/uri/tests/004.phpt index abbad59fee2e8..d22f52f30c48f 100644 --- a/ext/uri/tests/004.phpt +++ b/ext/uri/tests/004.phpt @@ -5,6 +5,9 @@ uri --FILE-- ---EXPECT-- +--EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} The specified URI is malformed (MissingSchemeNonRelativeUrl) NULL +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + NULL + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(20) "192.168/contact.html" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +NULL NULL NULL diff --git a/ext/uri/tests/005.phpt b/ext/uri/tests/005.phpt index 262d43a75406b..6db6c4a56ee5a 100644 --- a/ext/uri/tests/005.phpt +++ b/ext/uri/tests/005.phpt @@ -5,6 +5,8 @@ uri --FILE-- getAsciiHost()); @@ -14,6 +16,7 @@ var_dump($url->toUnicodeString()); ?> --EXPECTF-- +NULL object(Uri\WhatWg\Url)#%d (%d) { ["scheme"]=> string(4) "http" diff --git a/ext/uri/tests/006.phpt b/ext/uri/tests/006.phpt index 0aba3e9e46b5e..c4da9db905c82 100644 --- a/ext/uri/tests/006.phpt +++ b/ext/uri/tests/006.phpt @@ -5,11 +5,32 @@ uri --FILE-- --EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(8) "username" + ["password"]=> + string(8) "password" + ["host"]=> + string(11) "example.com" + ["port"]=> + int(8080) + ["path"]=> + string(5) "/path" + ["query"]=> + string(3) "q=r" + ["fragment"]=> + string(8) "fragment" +} object(Uri\WhatWg\Url)#%d (%d) { ["scheme"]=> string(5) "https" diff --git a/ext/uri/tests/007.phpt b/ext/uri/tests/007.phpt index cb445fcf71a43..54151f2dfcb1c 100644 --- a/ext/uri/tests/007.phpt +++ b/ext/uri/tests/007.phpt @@ -5,6 +5,12 @@ uri --FILE-- getMessage() . "\n"; +} + try { new Uri\WhatWg\Url("https://example.com:8080@username:password/path?q=r#fragment"); } catch (Uri\WhatWg\InvalidUrlException $e) { @@ -19,6 +25,7 @@ var_dump($failures); ?> --EXPECTF-- +The specified URI is malformed The specified URI is malformed (PortInvalid) array(%d) { [0]=> diff --git a/ext/uri/tests/008.phpt b/ext/uri/tests/008.phpt index f4fddcd8eb777..e13130bb4c466 100644 --- a/ext/uri/tests/008.phpt +++ b/ext/uri/tests/008.phpt @@ -5,6 +5,27 @@ uri --FILE-- getScheme()); + var_dump($uri->getRawScheme()); + var_dump($uri->getUsername()); + var_dump($uri->getRawUsername()); + var_dump($uri->getPassword()); + var_dump($uri->getRawPassword()); + var_dump($uri->getUserInfo()); + var_dump($uri->getRawUserInfo()); + var_dump($uri->getHost()); + var_dump($uri->getRawHost()); + var_dump($uri->getPort()); + var_dump($uri->getPath()); + var_dump($uri->getRawPath()); + var_dump($uri->getQuery()); + var_dump($uri->getRawQuery()); + var_dump($uri->getFragment()); + var_dump($uri->getRawFragment()); +} + function callWhatWgGetters($url) { var_dump($url->getScheme()); @@ -18,11 +39,34 @@ function callWhatWgGetters($url) var_dump($url->getFragment()); } +$uri = Uri\Rfc3986\Uri::parse("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists"); +callRfc3986Getters($uri); + +echo "\n"; + $url = Uri\WhatWg\Url::parse("https://username:password@www.google.com:8080/pathname1/pathname2/pathname3?query=true#hash-exists"); callWhatWgGetters($url); ?> --EXPECT-- +string(5) "https" +string(5) "https" +string(8) "username" +string(8) "username" +string(8) "password" +string(8) "password" +string(17) "username:password" +string(17) "username:password" +string(14) "www.google.com" +string(14) "www.google.com" +int(8080) +string(30) "/pathname1/pathname2/pathname3" +string(30) "/pathname1/pathname2/pathname3" +string(10) "query=true" +string(10) "query=true" +string(11) "hash-exists" +string(11) "hash-exists" + string(5) "https" string(8) "username" string(8) "password" diff --git a/ext/uri/tests/009.phpt b/ext/uri/tests/009.phpt index 1b279588c0167..05f2820bb3fcf 100644 --- a/ext/uri/tests/009.phpt +++ b/ext/uri/tests/009.phpt @@ -5,10 +5,29 @@ uri --FILE-- --EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(16) "chrome-extension" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL +} object(Uri\WhatWg\Url)#%d (%d) { ["scheme"]=> string(16) "chrome-extension" diff --git a/ext/uri/tests/010.phpt b/ext/uri/tests/010.phpt index 4ec13f652f60c..2ca071eb2ca33 100644 --- a/ext/uri/tests/010.phpt +++ b/ext/uri/tests/010.phpt @@ -5,11 +5,49 @@ uri --FILE-- --EXPECTF-- +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(4) "http" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(14) "/path/to/file2" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +object(Uri\Rfc3986\Uri)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(8) "test.com" + ["port"]=> + NULL + ["path"]=> + string(14) "/path/to/file2" + ["query"]=> + NULL + ["fragment"]=> + NULL +} object(Uri\WhatWg\Url)#%d (%d) { ["scheme"]=> string(4) "http" diff --git a/ext/uri/tests/011.phpt b/ext/uri/tests/011.phpt index 283886fb34fbb..49b915fa22a31 100644 --- a/ext/uri/tests/011.phpt +++ b/ext/uri/tests/011.phpt @@ -5,6 +5,12 @@ uri --FILE-- toRawString()); +var_dump(Uri\Rfc3986\Uri::parse("https://www.example.com/dir1/../dir2")->toRawString()); +var_dump(Uri\Rfc3986\Uri::parse("https://你好你好")); +var_dump(Uri\Rfc3986\Uri::parse("https://0Xc0.0250.01")); +var_dump(Uri\Rfc3986\Uri::parse("HttPs://0300.0250.0000.0001/path?query=foo%20bar")->toRawString()); + var_dump(Uri\WhatWg\Url::parse("http://////www.EXAMPLE.com:80")->toAsciiString()); var_dump(Uri\WhatWg\Url::parse("https://www.example.com:443/dir1/../dir2")->toAsciiString()); var_dump(Uri\WhatWg\Url::parse("https://你好你好")->toAsciiString()); @@ -14,6 +20,11 @@ var_dump(Uri\WhatWg\Url::parse("HttPs://0300.0250.0000.0001/path?query=foo%20bar ?> --EXPECT-- +string(29) "http://////www.EXAMPLE.com:80" +string(36) "https://www.example.com/dir1/../dir2" +NULL +NULL +string(48) "HttPs://0300.0250.0000.0001/path?query=foo%20bar" string(23) "http://www.example.com/" string(28) "https://www.example.com/dir2" string(23) "https://xn--6qqa088eba/" diff --git a/ext/uri/tests/012.phpt b/ext/uri/tests/012.phpt index 0784a74e625f0..3eb343af535cb 100644 --- a/ext/uri/tests/012.phpt +++ b/ext/uri/tests/012.phpt @@ -5,13 +5,15 @@ uri --FILE-- --EXPECTF-- -object(Uri\WhatWg\Url)#%d (%d) { +object(Uri\Rfc3986\Uri)#%d (%d) { ["scheme"]=> string(6) "mailto" ["username"]=> @@ -30,6 +32,24 @@ object(Uri\WhatWg\Url)#%d (%d) { NULL } object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(6) "mailto" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + NULL + ["port"]=> + NULL + ["path"]=> + string(15) "Joe@Example.COM" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +object(Uri\Rfc3986\Uri)#%d (%d) { ["scheme"]=> string(4) "file" ["username"]=> @@ -37,7 +57,25 @@ object(Uri\WhatWg\Url)#%d (%d) { ["password"]=> NULL ["host"]=> + string(0) "" + ["port"]=> NULL + ["path"]=> + string(30) "/E:/Documents%20and%20Settings" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(4) "file" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(0) "" ["port"]=> NULL ["path"]=> diff --git a/ext/uri/tests/013.phpt b/ext/uri/tests/013.phpt index 016fe6632782c..6a5bb31870fb1 100644 --- a/ext/uri/tests/013.phpt +++ b/ext/uri/tests/013.phpt @@ -5,14 +5,39 @@ uri --FILE-- + @")); + var_dump(Uri\WhatWg\Url::parse("http://example.com?foobar=%27%3Cscript%3E+%2B+%40")); var_dump(Uri\WhatWg\Url::parse("http://example.com?foobar='idential to those + of UriUriStructA.hostText at all times. */ } URI_TYPE(HostData); /**< @copydoc UriHostDataStructA */ @@ -201,6 +205,59 @@ typedef struct URI_TYPE(QueryListStruct) { } URI_TYPE(QueryList); /**< @copydoc UriQueryListStructA */ +/** + * Checks if a URI has the host component set. + * + * @param uri IN: %URI to check + * @return URI_TRUE when host is set, URI_FALSE otherwise + * + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(HasHost)(const URI_TYPE(Uri) * uri); + + + +/** + * Converts an IPv6 text representation into 16 bytes. + * + * Uses default libc-based memory manager. + * + * @param output OUT: Output destination, can be NULL + * @param first IN: First character of IPv6 text to parse + * @param afterLast IN: Position to stop parsing at + * @return Error code or URI_SUCCESS on success + * + * @see uriParseIpFourAddressA + * @see uriParseIpSixAddressMmA + * @see uriIsWellFormedHostIp6A + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(ParseIpSixAddress)(UriIp6 * output, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Converts an IPv6 text representation into 16 bytes. + * + * @param output OUT: Output destination, can be NULL + * @param first IN: First character of IPv6 text to parse + * @param afterLast IN: Position to stop parsing at + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or URI_SUCCESS on success + * + * @see uriParseIpFourAddressA + * @see uriParseIpSixAddressA + * @see uriIsWellFormedHostIp6MmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(ParseIpSixAddressMm)(UriIp6 * output, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + /** * Parses a RFC 3986 %URI. @@ -323,6 +380,10 @@ URI_PUBLIC int URI_FUNC(ParseSingleUriExMm)(URI_TYPE(Uri) * uri, * itself is not freed, only its members. * Uses default libc-based memory manager. * + * @remarks + * Calling on an all-zeros structure (e.g. through memset or calloc) is safe.
+ * Calling on an uninitialized structure is not safe. + * * @param uri INOUT: %URI structure whose members should be freed * * @see uriFreeUriMembersMmA @@ -337,6 +398,10 @@ URI_PUBLIC void URI_FUNC(FreeUriMembers)(URI_TYPE(Uri) * uri); * of the %URI structure. Note that the structure * itself is not freed, only its members. * + * @remarks + * Calling on an all-zeros structure (e.g. through memset or calloc) is safe.
+ * Calling on an uninitialized structure is not safe. + * * @param uri INOUT: %URI structure whose members should be freed * @param memory IN: Memory manager to use, NULL for default libc * @return 0 on success, error code otherwise @@ -644,6 +709,36 @@ URI_PUBLIC int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, +/** + * Copies a %URI structure. + * + * @param destUri OUT: Output destination + * @param sourceUri IN: %URI to copy + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriCopyUriA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(CopyUriMm)(URI_TYPE(Uri) * destUri, + const URI_TYPE(Uri) * sourceUri, UriMemoryManager * memory); + + + +/** + * Copies a %URI structure. + * + * @param destUri OUT: Output destination + * @param sourceUri IN: %URI to copy + * @return Error code or 0 on success + * + * @see uriCopyUriMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(CopyUri)(URI_TYPE(Uri) * destUri, const URI_TYPE(Uri) * sourceUri); + + + /** * Determines the components of a %URI that are not normalized. * @@ -1136,6 +1231,1202 @@ URI_PUBLIC int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, +/** + * Determines if the given text range contains a well-formed fragment + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetFragmentA + * @see uriSetFragmentMmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedFragment)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Determines if the given text range contains a well-formed IPv4 address + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetHostIp4A + * @see uriSetHostIp4MmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedHostIp4)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Determines if the given text range contains a well-formed IPv6 address + * according to RFC 3986 or not. + * + * Uses default libc-based memory manager. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_SUCCESS if non-NULL and well-formed, else an error code + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6MmA + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriParseIpSixAddressA + * @see uriParseIpSixAddressMmA + * @since 0.9.9 + */ +int URI_FUNC(IsWellFormedHostIp6)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Determines if the given text range contains a well-formed IPv6 address + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @param memory IN: Memory manager to use, NULL for default libc + * @return URI_SUCCESS if non-NULL and well-formed, else an error code + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureMmA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @since 0.9.9 + */ +int URI_FUNC(IsWellFormedHostIp6Mm)(const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); + + + +/** + * Determines if the given text range contains a well-formed IPvFuture address + * according to RFC 3986 or not. + * + * Uses default libc-based memory manager. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_SUCCESS if non-NULL and well-formed, else an error code + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureMmA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetHostIpFutureA + * @see uriSetHostIpFutureMmA + * @since 0.9.9 + */ +int URI_FUNC(IsWellFormedHostIpFuture)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Determines if the given text range contains a well-formed IPvFuture address + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @param memory IN: Memory manager to use, NULL for default libc + * @return URI_SUCCESS if non-NULL and well-formed, else an error code + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetHostIpFutureA + * @see uriSetHostIpFutureMmA + * @since 0.9.9 + */ +int URI_FUNC(IsWellFormedHostIpFutureMm)(const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); + + + +/** + * Determines if the given text range contains a well-formed registered host name + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetHostRegNameA + * @see uriSetHostRegNameMmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedHostRegName)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Determines if the given text range contains a well-formed path + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @param hasHost IN: Wether the target %URI has a non-NULL host set or not + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetPathA + * @see uriSetPathMmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedPath)(const URI_CHAR * first, const URI_CHAR * afterLast, UriBool hasHost); + + + +/** + * Determines if the given text range contains a well-formed port text + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetPortTextA + * @see uriSetPortTextMmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedPort)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Determines if the given text range contains a well-formed query + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetQueryA + * @see uriSetQueryMmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedQuery)(const URI_CHAR * first, const URI_CHAR * afterLast); + + +/** + * Determines if the given text range contains a well-formed scheme + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriIsWellFormedUserInfoA + * @see uriSetSchemeA + * @see uriSetSchemeMmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedScheme)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Determines if the given text range contains a well-formed user info + * according to RFC 3986 or not. + * + * @param first IN: Pointer to first character + * @param afterLast IN: Pointer to character after the last one still in + * @return URI_TRUE if non-NULL and well-formed, else URI_FALSE + * + * @see uriIsWellFormedFragmentA + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostRegNameA + * @see uriIsWellFormedPathA + * @see uriIsWellFormedPortA + * @see uriIsWellFormedQueryA + * @see uriIsWellFormedSchemeA + * @see uriSetUserInfoA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC UriBool URI_FUNC(IsWellFormedUserInfo)(const URI_CHAR * first, const URI_CHAR * afterLast); + + + +/** + * Sets the fragment of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedFragmentA + * @see uriSetFragmentMmA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetFragment)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the fragment of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedFragmentA + * @see uriSetFragmentA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetFragmentMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIp6MmA + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostIpFutureMmA + * @see uriIsWellFormedHostRegNameA + * @see uriSetFragmentA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostAuto)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp4A + * @see uriIsWellFormedHostIp6A + * @see uriIsWellFormedHostIp6MmA + * @see uriIsWellFormedHostIpFutureA + * @see uriIsWellFormedHostIpFutureMmA + * @see uriIsWellFormedHostRegNameA + * @see uriSetFragmentMmA + * @see uriSetHostAutoA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostAutoMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostRegNameA + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostRegName)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostRegNameA + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostRegNameMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp4A + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostIp4)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp4A + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4A + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostIp4Mm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp6A + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostIp6)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp6A + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6A + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostIp6Mm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp4A + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostIpFuture)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the host of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedHostIp4A + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetHostIpFutureMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the path of the given %URI to the given value. + * + * Non-NULL values must start with a leading slash for %URIs that have a host. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedPathA + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPathMmA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetPath)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the path of the given %URI to the given value. + * + * Non-NULL values must start with a leading slash for %URIs that have a host. + * + * The %URI must have a non-NULL host set. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedPathA + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPathA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetPathMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the port text of the given %URI to the given value. + * + * The %URI must have a non-NULL host set. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedPortA + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextMmA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetPortText)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the port text of the given %URI to the given value. + * + * The %URI must have a non-NULL host set. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedPortA + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetPortTextMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the query of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedQueryA + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryMmA + * @see uriSetSchemeA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetQuery)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the query of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedQueryA + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryA + * @see uriSetSchemeMmA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetQueryMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the scheme of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedSchemeA + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeMmA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetScheme)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the scheme of the given %URI to the given value. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedSchemeA + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetSchemeMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Sets the user info of the given %URI to the given value. + * + * The %URI must have a non-NULL host set. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * Uses default libc-based memory manager. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @return Error code or 0 on success + * + * @see uriIsWellFormedUserInfoA + * @see uriSetFragmentA + * @see uriSetHostAutoA + * @see uriSetHostIp4A + * @see uriSetHostIp6A + * @see uriSetHostIpFutureA + * @see uriSetHostRegNameA + * @see uriSetPortTextA + * @see uriSetQueryA + * @see uriSetSchemeA + * @see uriSetUserInfoMmA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetUserInfo)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast); + + + +/** + * Sets the user info of the given %URI to the given value. + * + * The %URI must have a non-NULL host set. + * + * Parameters first and afterLast must both be NULL + * or non-NULL at the same time. + * + * The function may make the %URI own its memory if needed (if it is not already owned). + * + * For all return values but URI_ERROR_MALLOC, all-or-nothing behavior + * can be expected, e.g. trying to apply a malformed value will leave the + * %URI unchanged. + * + * @param uri INOUT: %URI to modify + * @param first IN: Pointer to first character, can be NULL + * @param afterLast IN: Pointer to character after the last one still in, can be NULL + * @param memory IN: Memory manager to use, NULL for default libc + * @return Error code or 0 on success + * + * @see uriIsWellFormedUserInfoA + * @see uriSetFragmentMmA + * @see uriSetHostAutoMmA + * @see uriSetHostIp4MmA + * @see uriSetHostIp6MmA + * @see uriSetHostIpFutureMmA + * @see uriSetHostRegNameMmA + * @see uriSetPortTextMmA + * @see uriSetQueryMmA + * @see uriSetSchemeMmA + * @see uriSetUserInfoA + * @since 0.9.9 + */ +URI_PUBLIC int URI_FUNC(SetUserInfoMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +/** + * Obtain the base runtime version of uriparser. + * + * The string returned is based on the compile time version + * of uriparser. + * + * @note Distributors may have applied backports of security + * fixes (potentially with adjusting packaging version but often + * without adjusting runtime version) + * or even fully custom patches. As a result, the version string + * returned serves as nothing more than "based on that version", + * it does not guarantee equivalence to vanilla upstream releases + * or absence of additinal downstream patches. + * It is nothing more than "a hint" and MUST NEVER be used to + * make decisions on in application code at runtime. + * + * @return Pointer to a read-only zero terminated version string + * + * @since 0.9.9 + */ +URI_PUBLIC const URI_CHAR * URI_FUNC(BaseRuntimeVersion)(void); + + + #ifdef __cplusplus } #endif diff --git a/ext/uri/uriparser/include/uriparser/UriBase.h b/ext/uri/uriparser/include/uriparser/UriBase.h index dc3883e65167c..6b01bb79e9f86 100644 --- a/ext/uri/uriparser/include/uriparser/UriBase.h +++ b/ext/uri/uriparser/include/uriparser/UriBase.h @@ -48,14 +48,15 @@ /* Version helper macro */ -#define URI_ANSI_TO_UNICODE(x) L##x +#define URI_ANSI_TO_UNICODE_HELPER(x) L ## x +#define URI_ANSI_TO_UNICODE(x) URI_ANSI_TO_UNICODE_HELPER(x) /* Version */ #define URI_VER_MAJOR 0 #define URI_VER_MINOR 9 -#define URI_VER_RELEASE 8 +#define URI_VER_RELEASE 9 #define URI_VER_SUFFIX_ANSI "" #define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI) @@ -148,6 +149,17 @@ typedef int UriBool; /**< Boolean type */ /* Error specific to uriTestMemoryManager */ #define URI_ERROR_MEMORY_MANAGER_FAULTY 11 /* [>=0.9.0] The UriMemoryManager given did not pass the test suite */ +/* Error specific to uriSetUserInfo */ +#define URI_ERROR_SETUSERINFO_HOST_NOT_SET 12 /* [>=0.9.9] The %URI given does not have the host set */ + +/* Error specific to uriSetPort */ +#define URI_ERROR_SETPORT_HOST_NOT_SET 13 /* [>=0.9.9] The %URI given does not have the host set */ + +/* Error specific to uriSetHost* */ +#define URI_ERROR_SETHOST_USERINFO_SET 14 /* [>=0.9.9] The %URI given does have user info set */ +#define URI_ERROR_SETHOST_PORT_SET 15 /* [>=0.9.9] The %URI given does have a port set */ + + #ifndef URI_DOXYGEN # include /* For NULL, snprintf */ @@ -258,7 +270,8 @@ typedef enum UriNormalizationMaskEnum { URI_NORMALIZE_HOST = 1 << 2, /**< Normalize host (fix uppercase letters) */ URI_NORMALIZE_PATH = 1 << 3, /**< Normalize path (fix uppercase percent-encodings and redundant dot segments) */ URI_NORMALIZE_QUERY = 1 << 4, /**< Normalize query (fix uppercase percent-encodings) */ - URI_NORMALIZE_FRAGMENT = 1 << 5 /**< Normalize fragment (fix uppercase percent-encodings) */ + URI_NORMALIZE_FRAGMENT = 1 << 5, /**< Normalize fragment (fix uppercase percent-encodings) */ + URI_NORMALIZE_PORT = 1 << 6 /**< Normalize port (drop leading zeros) @since 0.9.9 */ } UriNormalizationMask; /**< @copydoc UriNormalizationMaskEnum */ diff --git a/ext/uri/uriparser/include/uriparser/UriIp4.h b/ext/uri/uriparser/include/uriparser/UriIp4.h index c2e59a6bf2d13..4b847abe3ab7c 100644 --- a/ext/uri/uriparser/include/uriparser/UriIp4.h +++ b/ext/uri/uriparser/include/uriparser/UriIp4.h @@ -88,12 +88,15 @@ extern "C" { /** - * Converts a IPv4 text representation into four bytes. + * Converts an IPv4 text representation into four bytes. * * @param octetOutput Output destination * @param first First character of IPv4 text to parse * @param afterLast Position to stop parsing at * @return Error code or 0 on success + * + * @see uriParseIpSixAddressA + * @see uriParseIpSixAddressMmA */ URI_PUBLIC int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput, const URI_CHAR * first, const URI_CHAR * afterLast); diff --git a/ext/uri/uriparser/src/COPYING b/ext/uri/uriparser/src/COPYING new file mode 100644 index 0000000000000..261c741da0fba --- /dev/null +++ b/ext/uri/uriparser/src/COPYING @@ -0,0 +1,36 @@ +uriparser - RFC 3986 URI parsing library + +Copyright (C) 2007, Weijia Song +Copyright (C) 2007, Sebastian Pipping +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ext/uri/uriparser/src/UriCommon.c b/ext/uri/uriparser/src/UriCommon.c index 88e2767d71cb2..2d4e947088bc6 100644 --- a/ext/uri/uriparser/src/UriCommon.c +++ b/ext/uri/uriparser/src/UriCommon.c @@ -68,6 +68,10 @@ +#include + + + /*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X"); /*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT("."); /*extern*/ const URI_CHAR * const URI_FUNC(ConstParent) = _UT(".."); @@ -83,6 +87,32 @@ void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) { +int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { + assert(uri != NULL); + assert(memory != NULL); + + if (uri->pathHead != NULL) { + URI_TYPE(PathSegment) * segWalk = uri->pathHead; + while (segWalk != NULL) { + URI_TYPE(PathSegment) * const next = segWalk->next; + if ((uri->owner == URI_TRUE) && (segWalk->text.first != segWalk->text.afterLast)) { + memory->free(memory, (URI_CHAR *)segWalk->text.first); + } + segWalk->text.first = NULL; + segWalk->text.afterLast = NULL; + segWalk->next = NULL; + memory->free(memory, segWalk); + segWalk = next; + } + uri->pathHead = NULL; + uri->pathTail = NULL; + } + + return URI_SUCCESS; +} + + + /* Compares two text ranges for equal text content */ int URI_FUNC(CompareRange)( const URI_TYPE(TextRange) * a, @@ -119,6 +149,40 @@ int URI_FUNC(CompareRange)( +UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange, + const URI_TYPE(TextRange) * sourceRange, UriMemoryManager * memory) { + const int lenInChars = (int)(sourceRange->afterLast - sourceRange->first); + const int lenInBytes = lenInChars * sizeof(URI_CHAR); + URI_CHAR * dup = memory->malloc(memory, lenInBytes); + if (dup == NULL) { + return URI_FALSE; + } + memcpy(dup, sourceRange->first, lenInBytes); + destRange->first = dup; + destRange->afterLast = dup + lenInChars; + + return URI_TRUE; +} + + + +UriBool URI_FUNC(CopyRangeAsNeeded)(URI_TYPE(TextRange) * destRange, + const URI_TYPE(TextRange) * sourceRange, UriMemoryManager * memory) { + if (sourceRange->first == NULL) { + destRange->first = NULL; + destRange->afterLast = NULL; + } else if (sourceRange->first == sourceRange->afterLast) { + destRange->first = URI_FUNC(SafeToPointTo); + destRange->afterLast = URI_FUNC(SafeToPointTo); + } else { + return URI_FUNC(CopyRange)(destRange, sourceRange, memory); + } + + return URI_TRUE; +} + + + UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool relative, UriBool pathOwned, UriMemoryManager * memory) { URI_TYPE(PathSegment) * walker; @@ -189,7 +253,7 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, if (prev == NULL) { /* Last and first */ - if (URI_FUNC(IsHostSet)(uri)) { + if (URI_FUNC(HasHost)(uri)) { /* Replace "." with empty segment to represent trailing slash */ walker->text.first = URI_FUNC(SafeToPointTo); walker->text.afterLast = URI_FUNC(SafeToPointTo); @@ -430,14 +494,6 @@ unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) { -URI_CHAR URI_FUNC(HexToLetter)(unsigned int value) { - /* Uppercase recommended in section 2.1. of RFC 3986 * - * https://datatracker.ietf.org/doc/html/rfc3986#section-2.1 */ - return URI_FUNC(HexToLetterEx)(value, URI_TRUE); -} - - - URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase) { switch (value) { case 0: return _UT('0'); @@ -463,12 +519,16 @@ URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase) { /* Checks if a URI has the host component set. */ -UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri) { +UriBool URI_FUNC(HasHost)(const URI_TYPE(Uri) * uri) { + /* NOTE: .hostData.ipFuture.first is not being checked, * + * because we do check .hostText.first and * + * .hostData.ipFuture.first has to be identical to * + * .hostText.first if set, and hence there is * + * no more information to be gained. */ return (uri != NULL) && ((uri->hostText.first != NULL) || (uri->hostData.ip4 != NULL) || (uri->hostData.ip6 != NULL) - || (uri->hostData.ipFuture.first != NULL) ); } @@ -597,11 +657,135 @@ UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, +static UriBool URI_FUNC(PrependNewDotSegment)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { + assert(uri != NULL); + assert(memory != NULL); + + { + URI_TYPE(PathSegment) * const segment = memory->malloc(memory, 1 * sizeof(URI_TYPE(PathSegment))); + + if (segment == NULL) { + return URI_FALSE; /* i.e. raise malloc error */ + } + + segment->next = uri->pathHead; + + { + URI_TYPE(TextRange) dotRange; + dotRange.first = URI_FUNC(ConstPwd); + dotRange.afterLast = URI_FUNC(ConstPwd) + 1; + + if (uri->owner == URI_TRUE) { + if (URI_FUNC(CopyRange)(&(segment->text), &dotRange, memory) == URI_FALSE) { + memory->free(memory, segment); + return URI_FALSE; /* i.e. raise malloc error */ + } + } else { + segment->text = dotRange; /* copies all members */ + } + } + + uri->pathHead = segment; + } + + return URI_TRUE; +} + + + +/* When dropping a scheme from a URI without a host and with a colon (":") + * in the first path segment, a consecutive reparse would rightfully + * mis-classify the first path segment as a scheme due to the colon. + * To protect against this case, we prepend an artifical "." segment + * to the path in here; the function is called after the scheme has + * just been dropped. + * + * 0. We start with parsed URI "scheme:path1:/path2/path3". + * 1. We drop the scheme naively and yield "path1:/path2/path3". + * 2. We prepend "." and yield unambiguous "./path1:/path2/path3". + * + * From the view of the RFC 3986 grammar, this is replacing rule path-rootless + * by path-noscheme content. + * + * Returns URI_TRUE for (a) nothing to do or (b) successful changes. + * Returns URI_FALSE to signal out-of-memory. + */ +UriBool URI_FUNC(FixPathNoScheme)(URI_TYPE(Uri) * uri, + UriMemoryManager * memory) { + assert(uri != NULL); + assert(memory != NULL); + + if ((uri->absolutePath == URI_TRUE) + || (uri->pathHead == NULL) + || (uri->scheme.first != NULL) + || URI_FUNC(HasHost)(uri)) { + return URI_TRUE; /* i.e. nothing to do */ + } + + /* Check for troublesome first path segment containing a colon */ + { + UriBool colonFound = URI_FALSE; + const URI_CHAR * walker = uri->pathHead->text.first; + + while (walker < uri->pathHead->text.afterLast) { + if (walker[0] == _UT(':')) { + colonFound = URI_TRUE; + break; + } + walker++; + } + + assert((walker == uri->pathHead->text.afterLast) || (colonFound == URI_TRUE)); + + if (colonFound == URI_FALSE) { + return URI_TRUE; /* i.e. nothing to do */ + } + } + + /* Insert "." segment in front */ + return URI_FUNC(PrependNewDotSegment)(uri, memory); +} + + + +/* When dropping a host from a URI without a scheme, an absolute path + * and and empty first path segment, a consecutive reparse would rightfully + * mis-classify the first path segment as a host marker due to the "//". + * To protect against this case, we prepend an artifical "." segment + * to the path in here; the function is called after the host has + * just been dropped. + * + * 0. We start with parsed URI "//host//path1/path2". + * 1. We drop the host naively and yield "//path1/path2". + * 2. We insert "./" and yield unambiguous "/.//path1/path2". + * + * Returns URI_TRUE for (a) nothing to do or (b) successful changes. + * Returns URI_FALSE to signal out-of-memory. + */ +UriBool URI_FUNC(EnsureThatPathIsNotMistakenForHost)(URI_TYPE(Uri) * uri, + UriMemoryManager * memory) { + assert(uri != NULL); + assert(memory != NULL); + + if ((URI_FUNC(HasHost)(uri) == URI_TRUE) + || (uri->absolutePath == URI_FALSE) + || (uri->pathHead == NULL) + || (uri->pathHead == uri->pathTail) /* i.e. no second slash */ + || (uri->pathHead->text.first != uri->pathHead->text.afterLast)) { + return URI_TRUE; /* i.e. nothing to do */ + } + + /* Insert "." segment in front */ + return URI_FUNC(PrependNewDotSegment)(uri, memory); +} + + + void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { /* Fix path if only one empty segment */ if (!uri->absolutePath - && !URI_FUNC(IsHostSet)(uri) + && !URI_FUNC(HasHost)(uri) && (uri->pathHead != NULL) && (uri->pathHead->next == NULL) && (uri->pathHead->text.first == uri->pathHead->text.afterLast)) { diff --git a/ext/uri/uriparser/src/UriCommon.h b/ext/uri/uriparser/src/UriCommon.h index 42311ddc98b2d..96beb087a03d3 100644 --- a/ext/uri/uriparser/src/UriCommon.h +++ b/ext/uri/uriparser/src/UriCommon.h @@ -78,27 +78,33 @@ extern const URI_CHAR * const URI_FUNC(ConstParent); void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri); +int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); + int URI_FUNC(CompareRange)( const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b); +UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange, + const URI_TYPE(TextRange) * sourceRange, UriMemoryManager * memory); +UriBool URI_FUNC(CopyRangeAsNeeded)(URI_TYPE(TextRange) * destRange, + const URI_TYPE(TextRange) * sourceRange, UriMemoryManager * memory); + UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool relative, UriBool pathOwned, UriMemoryManager * memory); unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig); -URI_CHAR URI_FUNC(HexToLetter)(unsigned int value); URI_CHAR URI_FUNC(HexToLetterEx)(unsigned int value, UriBool uppercase); -UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri); - UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source, UriMemoryManager * memory); UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest, const URI_TYPE(Uri) * source, UriMemoryManager * memory); UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); +UriBool URI_FUNC(FixPathNoScheme)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); +UriBool URI_FUNC(EnsureThatPathIsNotMistakenForHost)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); void URI_FUNC(FixEmptyTrailSegment)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); diff --git a/ext/uri/uriparser/src/UriConfig.h b/ext/uri/uriparser/src/UriConfig.h index 3139da04f72c1..8c58a3222e210 100644 --- a/ext/uri/uriparser/src/UriConfig.h +++ b/ext/uri/uriparser/src/UriConfig.h @@ -41,7 +41,7 @@ -#define PACKAGE_VERSION "0.9.8" +#define PACKAGE_VERSION "@PROJECT_VERSION@" /* #define HAVE_WPRINTF* diff --git a/ext/uri/uriparser/src/UriCopy.c b/ext/uri/uriparser/src/UriCopy.c new file mode 100644 index 0000000000000..85f2a8aa17926 --- /dev/null +++ b/ext/uri/uriparser/src/UriCopy.c @@ -0,0 +1,239 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * Copyright (C) 2025, Máté Kocsis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriCopy.c + * Holds the RFC 3986 %URI normalization implementation. + * NOTE: This source file includes itself twice. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriCopy.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriCopy.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +# include "UriNormalize.h" +# include "UriCopy.h" +#endif + + + +static void URI_FUNC(PreventLeakageAfterCopy)(URI_TYPE(Uri) * uri, + unsigned int revertMask, UriMemoryManager * memory) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); + + if (uri->hostData.ip4 != NULL) { + memory->free(memory, uri->hostData.ip4); + uri->hostData.ip4 = NULL; + } else if (uri->hostData.ip6 != NULL) { + memory->free(memory, uri->hostData.ip6); + uri->hostData.ip6 = NULL; + } + + if (revertMask & URI_NORMALIZE_PORT) { + if (uri->portText.first != uri->portText.afterLast) { + memory->free(memory, (URI_CHAR *)uri->portText.first); + } + uri->portText.first = NULL; + uri->portText.afterLast = NULL; + } +} + + + +int URI_FUNC(CopyUriMm)(URI_TYPE(Uri) * destUri, + const URI_TYPE(Uri) * sourceUri, UriMemoryManager * memory) { + unsigned int revertMask = URI_NORMALIZED; + + if (sourceUri == NULL || destUri == NULL) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + URI_FUNC(ResetUri)(destUri); + + if (URI_FUNC(CopyRangeAsNeeded)(&destUri->scheme, &sourceUri->scheme, memory) == URI_FALSE) { + return URI_ERROR_MALLOC; + } + + revertMask |= URI_NORMALIZE_SCHEME; + + if (URI_FUNC(CopyRangeAsNeeded)(&destUri->userInfo, &sourceUri->userInfo, memory) == URI_FALSE) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + revertMask |= URI_NORMALIZE_USER_INFO; + + if (URI_FUNC(CopyRangeAsNeeded)(&destUri->hostText, &sourceUri->hostText, memory) == URI_FALSE) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + revertMask |= URI_NORMALIZE_HOST; + + if (sourceUri->hostData.ip4 == NULL) { + destUri->hostData.ip4 = NULL; + } else { + destUri->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4)); + if (destUri->hostData.ip4 == NULL) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + *(destUri->hostData.ip4) = *(sourceUri->hostData.ip4); + } + + if (sourceUri->hostData.ip6 == NULL) { + destUri->hostData.ip6 = NULL; + } else { + destUri->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6)); + if (destUri->hostData.ip6 == NULL) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + *(destUri->hostData.ip6) = *(sourceUri->hostData.ip6); + } + + if (sourceUri->hostData.ipFuture.first != NULL) { + destUri->hostData.ipFuture.first = destUri->hostText.first; + destUri->hostData.ipFuture.afterLast = destUri->hostText.afterLast; + } else if (URI_FUNC(CopyRangeAsNeeded)(&destUri->hostData.ipFuture, &sourceUri->hostData.ipFuture, memory) == URI_FALSE) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + if (URI_FUNC(CopyRangeAsNeeded)(&destUri->portText, &sourceUri->portText, memory) == URI_FALSE) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + revertMask |= URI_NORMALIZE_PORT; + + destUri->pathHead = NULL; + destUri->pathTail = NULL; + + if (sourceUri->pathHead != NULL) { + URI_TYPE(PathSegment) * sourceWalker = sourceUri->pathHead; + URI_TYPE(PathSegment) * destPrev = NULL; + + while (sourceWalker != NULL) { + URI_TYPE(PathSegment) * destWalker = memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); + if (destWalker == NULL) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + destWalker->text.first = NULL; + destWalker->text.afterLast = NULL; + destWalker->next = NULL; + destWalker->reserved = NULL; + + if (destUri->pathHead == NULL) { + destUri->pathHead = destWalker; + revertMask |= URI_NORMALIZE_PATH; + } + + if (URI_FUNC(CopyRangeAsNeeded)(&destWalker->text, &sourceWalker->text, memory) == URI_FALSE) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + if (destPrev != NULL) { + destPrev->next = destWalker; + } + + destPrev = destWalker; + sourceWalker = sourceWalker->next; + + destUri->pathTail = destWalker; + } + } + + if (URI_FUNC(CopyRangeAsNeeded)(&destUri->query, &sourceUri->query, memory) == URI_FALSE) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + revertMask |= URI_NORMALIZE_QUERY; + + if (URI_FUNC(CopyRangeAsNeeded)(&destUri->fragment, &sourceUri->fragment, memory) == URI_FALSE) { + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); + return URI_ERROR_MALLOC; + } + + destUri->absolutePath = sourceUri->absolutePath; + destUri->owner = URI_TRUE; + destUri->reserved = NULL; + + return URI_SUCCESS; +} + + + +int URI_FUNC(CopyUri)(URI_TYPE(Uri) * destUri, + const URI_TYPE(Uri) * sourceUri) { + return URI_FUNC(CopyUriMm)(destUri, sourceUri, NULL); +} + +#endif diff --git a/ext/uri/uriparser/src/UriCopy.h b/ext/uri/uriparser/src/UriCopy.h new file mode 100644 index 0000000000000..952b1df4f9cb3 --- /dev/null +++ b/ext/uri/uriparser/src/UriCopy.h @@ -0,0 +1,78 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2007, Weijia Song + * Copyright (C) 2007, Sebastian Pipping + * Copyright (C) 2025, Máté Kocsis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if (defined(URI_PASS_ANSI) && !defined(URI_COPY_H_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_COPY_H_UNICODE)) \ + || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriCopy.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriCopy.h" +# undef URI_PASS_UNICODE +# endif +/* Only one pass for each encoding */ +#elif (defined(URI_PASS_ANSI) && !defined(URI_COPY_H_ANSI) \ + && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ + && !defined(URI_COPY_H_UNICODE) && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_COPY_H_ANSI 1 +# include +# else +# define URI_COPY_H_UNICODE 1 +# include +# endif + + + +int URI_FUNC(CopyUriMm)(URI_TYPE(Uri) * destUri, + const URI_TYPE(Uri) * sourceUri, UriMemoryManager * memory); +int URI_FUNC(CopyUri)(URI_TYPE(Uri) * destUri, + const URI_TYPE(Uri) * sourceUri); + +#endif +#endif diff --git a/ext/uri/uriparser/src/UriEscape.c b/ext/uri/uriparser/src/UriEscape.c index ab8305fa9735c..366955f4adad4 100644 --- a/ext/uri/uriparser/src/UriEscape.c +++ b/ext/uri/uriparser/src/UriEscape.c @@ -229,9 +229,12 @@ URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst, /* Percent encode */ { const unsigned char code = (unsigned char)read[0]; + /* Uppercase recommended in (last sentence of) section 2.1 * + * of RFC 3986: * + * https://datatracker.ietf.org/doc/html/rfc3986#section-2.1 */ write[0] = _UT('%'); - write[1] = URI_FUNC(HexToLetter)(code >> 4); - write[2] = URI_FUNC(HexToLetter)(code & 0x0f); + write[1] = URI_FUNC(HexToLetterEx)(code >> 4, URI_TRUE); + write[2] = URI_FUNC(HexToLetterEx)(code & 0x0f, URI_TRUE); write += 3; } prevWasCr = URI_FALSE; diff --git a/ext/uri/uriparser/src/UriNormalize.c b/ext/uri/uriparser/src/UriNormalize.c index 0cf353f111119..631d9a05a4d95 100644 --- a/ext/uri/uriparser/src/UriNormalize.c +++ b/ext/uri/uriparser/src/UriNormalize.c @@ -83,11 +83,11 @@ static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask, unsigned int * outMask, UriMemoryManager * memory); -static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask, +static UriBool URI_FUNC(MakeRangeOwner)(unsigned int * revertMask, unsigned int maskTest, URI_TYPE(TextRange) * range, UriMemoryManager * memory); static UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri, - unsigned int * doneMask, UriMemoryManager * memory); + unsigned int * revertMask, UriMemoryManager * memory); static void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * first, const URI_CHAR ** afterLast); @@ -109,12 +109,9 @@ static void URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * fir static UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first, const URI_CHAR ** afterLast, UriMemoryManager * memory); -static void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, - unsigned int revertMask, UriMemoryManager * memory); - -static URI_INLINE void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, +void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, unsigned int revertMask, UriMemoryManager * memory) { if (revertMask & URI_NORMALIZE_SCHEME) { /* NOTE: A scheme cannot be the empty string @@ -332,10 +329,10 @@ static URI_INLINE void URI_FUNC(FixPercentEncodingEngine)( write++; } else { /* 6.2.2.1 Case Normalization: * - * lowercase percent-encodings */ + * uppercase percent-encodings */ write[0] = _UT('%'); - write[1] = URI_FUNC(HexToLetter)(left); - write[2] = URI_FUNC(HexToLetter)(right); + write[1] = URI_FUNC(HexToLetterEx)(left, URI_TRUE); + write[2] = URI_FUNC(HexToLetterEx)(right, URI_TRUE); write += 3; } @@ -400,23 +397,17 @@ static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** f -static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask, +static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * revertMask, unsigned int maskTest, URI_TYPE(TextRange) * range, UriMemoryManager * memory) { - if (((*doneMask & maskTest) == 0) + if (((*revertMask & maskTest) == 0) && (range->first != NULL) && (range->afterLast != NULL) && (range->afterLast > range->first)) { - const int lenInChars = (int)(range->afterLast - range->first); - const int lenInBytes = lenInChars * sizeof(URI_CHAR); - URI_CHAR * dup = memory->malloc(memory, lenInBytes); - if (dup == NULL) { - return URI_FALSE; /* Raises malloc error */ + if (URI_FUNC(CopyRange)(range, range, memory) == URI_FALSE) { + return URI_FALSE; } - memcpy(dup, range->first, lenInBytes); - range->first = dup; - range->afterLast = dup + lenInChars; - *doneMask |= maskTest; + *revertMask |= maskTest; } return URI_TRUE; } @@ -424,24 +415,24 @@ static URI_INLINE UriBool URI_FUNC(MakeRangeOwner)(unsigned int * doneMask, static URI_INLINE UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri, - unsigned int * doneMask, UriMemoryManager * memory) { + unsigned int * revertMask, UriMemoryManager * memory) { URI_TYPE(PathSegment) * walker = uri->pathHead; - if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_SCHEME, + if (!URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_SCHEME, &(uri->scheme), memory) - || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_USER_INFO, + || !URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_USER_INFO, &(uri->userInfo), memory) - || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_QUERY, + || !URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_QUERY, &(uri->query), memory) - || !URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_FRAGMENT, + || !URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_FRAGMENT, &(uri->fragment), memory)) { return URI_FALSE; /* Raises malloc error */ } /* Host */ - if ((*doneMask & URI_NORMALIZE_HOST) == 0) { + if ((*revertMask & URI_NORMALIZE_HOST) == 0) { if (uri->hostData.ipFuture.first != NULL) { /* IPvFuture */ - if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST, + if (!URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_HOST, &(uri->hostData.ipFuture), memory)) { return URI_FALSE; /* Raises malloc error */ } @@ -449,7 +440,7 @@ static URI_INLINE UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri, uri->hostText.afterLast = uri->hostData.ipFuture.afterLast; } else if (uri->hostText.first != NULL) { /* Regname */ - if (!URI_FUNC(MakeRangeOwner)(doneMask, URI_NORMALIZE_HOST, + if (!URI_FUNC(MakeRangeOwner)(revertMask, URI_NORMALIZE_HOST, &(uri->hostText), memory)) { return URI_FALSE; /* Raises malloc error */ } @@ -457,9 +448,9 @@ static URI_INLINE UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri, } /* Path */ - if ((*doneMask & URI_NORMALIZE_PATH) == 0) { + if ((*revertMask & URI_NORMALIZE_PATH) == 0) { while (walker != NULL) { - if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(walker->text), memory)) { + if (!URI_FUNC(MakeRangeOwner)(revertMask, 0, &(walker->text), memory)) { /* Free allocations done so far and kill path */ /* Kill path to one before walker (if any) */ @@ -488,13 +479,13 @@ static URI_INLINE UriBool URI_FUNC(MakeOwnerEngine)(URI_TYPE(Uri) * uri, } walker = walker->next; } - *doneMask |= URI_NORMALIZE_PATH; + *revertMask |= URI_NORMALIZE_PATH; } /* Port text, must come last so we don't have to undo that one if it fails. * * Otherwise we would need and extra enum flag for it although the port * * cannot go unnormalized... */ - if (!URI_FUNC(MakeRangeOwner)(doneMask, 0, &(uri->portText), memory)) { + if (!URI_FUNC(MakeRangeOwner)(revertMask, 0, &(uri->portText), memory)) { return URI_FALSE; /* Raises malloc error */ } @@ -557,11 +548,80 @@ int URI_FUNC(NormalizeSyntax)(URI_TYPE(Uri) * uri) { } +static const URI_CHAR * URI_FUNC(PastLeadingZeros)(const URI_CHAR * first, const URI_CHAR * afterLast) { + assert(first != NULL); + assert(afterLast != NULL); + assert(first != afterLast); + + { + /* Find the first non-zero character */ + const URI_CHAR * remainderFirst = first; + while ((remainderFirst < afterLast) && (remainderFirst[0] == _UT('0'))) { + remainderFirst++; + } + + /* Is the string /all/ zeros? */ + if (remainderFirst == afterLast) { + /* Yes, and length is >=1 because we ruled out the empty string earlier; + * pull back onto rightmost zero */ + assert(remainderFirst > first); + remainderFirst--; + assert(remainderFirst[0] == _UT('0')); + } + + return remainderFirst; + } +} + + + +static void URI_FUNC(DropLeadingZerosInplace)(URI_CHAR * first, const URI_CHAR ** afterLast) { + assert(first != NULL); + assert(afterLast != NULL); + assert(*afterLast != NULL); + + if (first == *afterLast) { + return; + } + + { + const URI_CHAR * const remainderFirst = URI_FUNC(PastLeadingZeros)(first, *afterLast); + + if (remainderFirst > first) { + const size_t remainderLen = *afterLast - remainderFirst; + memmove(first, remainderFirst, remainderLen * sizeof(URI_CHAR)); + first[remainderLen] = _UT('\0'); + *afterLast = first + remainderLen; + } + } +} + + + +static void URI_FUNC(AdvancePastLeadingZeros)( + const URI_CHAR ** first, const URI_CHAR * afterLast) { + assert(first != NULL); + assert(*first != NULL); + assert(afterLast != NULL); + + if (*first == afterLast) { + return; + } + + { + const URI_CHAR * const remainderFirst = URI_FUNC(PastLeadingZeros)(*first, afterLast); + + /* Cut off leading zeros */ + *first = remainderFirst; + } +} + + static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask, unsigned int * outMask, UriMemoryManager * memory) { - unsigned int doneMask = URI_NORMALIZED; + unsigned int revertMask = URI_NORMALIZED; /* Not just doing inspection? -> memory manager required! */ if (outMask == NULL) { @@ -611,10 +671,10 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, URI_FUNC(LowercaseInplace)(uri->scheme.first, uri->scheme.afterLast); } else { if (!URI_FUNC(LowercaseMalloc)(&(uri->scheme.first), &(uri->scheme.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } - doneMask |= URI_NORMALIZE_SCHEME; + revertMask |= URI_NORMALIZE_SCHEME; } } @@ -628,10 +688,10 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, } else { if (!URI_FUNC(LowercaseMalloc)(&(uri->hostData.ipFuture.first), &(uri->hostData.ipFuture.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } - doneMask |= URI_NORMALIZE_HOST; + revertMask |= URI_NORMALIZE_HOST; } uri->hostText.first = uri->hostData.ipFuture.first; uri->hostText.afterLast = uri->hostData.ipFuture.afterLast; @@ -646,10 +706,10 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, &(uri->hostText.first), &(uri->hostText.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } - doneMask |= URI_NORMALIZE_HOST; + revertMask |= URI_NORMALIZE_HOST; } URI_FUNC(LowercaseInplaceExceptPercentEncoding)(uri->hostText.first, @@ -658,6 +718,27 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, } } + /* Port */ + if (outMask != NULL) { + /* Is there a port even? */ + if (uri->portText.first != NULL) { + /* Determine whether the port is already normalized, i.e. either "", "0" or no leading zeros */ + const size_t portLen = uri->portText.afterLast - uri->portText.first; + if ((portLen > 1) && (uri->portText.first[0] == _UT('0'))) { + *outMask |= URI_NORMALIZE_PORT; + } + } + } else { + /* Normalize the port, i.e. drop leading zeros (except for string "0") */ + if ((inMask & URI_NORMALIZE_PORT) && (uri->portText.first != NULL)) { + if (uri->owner) { + URI_FUNC(DropLeadingZerosInplace)((URI_CHAR *)uri->portText.first, &(uri->portText.afterLast)); + } else { + URI_FUNC(AdvancePastLeadingZeros)(&(uri->portText.first), uri->portText.afterLast); + } + } + } + /* User info */ if (outMask != NULL) { const UriBool normalizeUserInfo = URI_FUNC(ContainsUglyPercentEncoding)( @@ -672,10 +753,10 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, } else { if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->userInfo.first), &(uri->userInfo.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } - doneMask |= URI_NORMALIZE_USER_INFO; + revertMask |= URI_NORMALIZE_USER_INFO; } } } @@ -720,20 +801,20 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, while (walker != NULL) { if (!URI_FUNC(FixPercentEncodingMalloc)(&(walker->text.first), &(walker->text.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } walker = walker->next; } - doneMask |= URI_NORMALIZE_PATH; + revertMask |= URI_NORMALIZE_PATH; } /* 6.2.2.3 Path Segment Normalization */ if (!URI_FUNC(RemoveDotSegmentsEx)(uri, relative, (uri->owner == URI_TRUE) - || ((doneMask & URI_NORMALIZE_PATH) != 0), + || ((revertMask & URI_NORMALIZE_PATH) != 0), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } URI_FUNC(FixEmptyTrailSegment)(uri, memory); @@ -760,10 +841,10 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, } else { if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->query.first), &(uri->query.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } - doneMask |= URI_NORMALIZE_QUERY; + revertMask |= URI_NORMALIZE_QUERY; } } @@ -774,18 +855,18 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, } else { if (!URI_FUNC(FixPercentEncodingMalloc)(&(uri->fragment.first), &(uri->fragment.afterLast), memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } - doneMask |= URI_NORMALIZE_FRAGMENT; + revertMask |= URI_NORMALIZE_FRAGMENT; } } } /* Dup all not duped yet */ if ((outMask == NULL) && !uri->owner) { - if (!URI_FUNC(MakeOwnerEngine)(uri, &doneMask, memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + if (!URI_FUNC(MakeOwnerEngine)(uri, &revertMask, memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } uri->owner = URI_TRUE; @@ -797,7 +878,7 @@ static URI_INLINE int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { - unsigned int doneMask = URI_NORMALIZED; + unsigned int revertMask = URI_NORMALIZED; URI_CHECK_MEMORY_MANAGER(memory); /* may return */ @@ -809,8 +890,8 @@ int URI_FUNC(MakeOwnerMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { return URI_SUCCESS; } - if (! URI_FUNC(MakeOwnerEngine)(uri, &doneMask, memory)) { - URI_FUNC(PreventLeakage)(uri, doneMask, memory); + if (! URI_FUNC(MakeOwnerEngine)(uri, &revertMask, memory)) { + URI_FUNC(PreventLeakage)(uri, revertMask, memory); return URI_ERROR_MALLOC; } diff --git a/ext/uri/uriparser/src/UriNormalize.h b/ext/uri/uriparser/src/UriNormalize.h new file mode 100644 index 0000000000000..cb58085b7d318 --- /dev/null +++ b/ext/uri/uriparser/src/UriNormalize.h @@ -0,0 +1,76 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2018, Weijia Song + * Copyright (C) 2018, Sebastian Pipping + * Copyright (C) 2025, Máté Kocsis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if (defined(URI_PASS_ANSI) && !defined(URI_NORMALIZE_H_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_NORMALIZE_H_UNICODE)) \ + || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriNormalize.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriNormalize.h" +# undef URI_PASS_UNICODE +# endif +/* Only one pass for each encoding */ +#elif (defined(URI_PASS_ANSI) && !defined(URI_NORMALIZE_H_ANSI) \ + && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ + && !defined(URI_NORMALIZE_H_UNICODE) && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_NORMALIZE_H_ANSI 1 +# include +# else +# define URI_NORMALIZE_H_UNICODE 1 +# include +# endif + + + +void URI_FUNC(PreventLeakage)(URI_TYPE(Uri) * uri, + unsigned int revertMask, UriMemoryManager * memory); + +#endif +#endif diff --git a/ext/uri/uriparser/src/UriParse.c b/ext/uri/uriparser/src/UriParse.c index a672c8eb1f2fc..8bb18f65ac166 100644 --- a/ext/uri/uriparser/src/UriParse.c +++ b/ext/uri/uriparser/src/UriParse.c @@ -480,7 +480,7 @@ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, case _UT('v'): case _UT('V'): */ - if (first + 1 >= afterLast) { + if (afterLast - first < 2) { URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; } @@ -755,7 +755,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)( } /* "::"? */ - if (first + 1 >= afterLast) { + if (afterLast - first < 2) { URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; } @@ -773,7 +773,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)( setZipper = 1; /* ":::+"? */ - if (first + 1 >= afterLast) { + if (afterLast - first < 2) { URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; /* No ']' yet */ } @@ -1583,14 +1583,14 @@ static const URI_CHAR * URI_FUNC(ParsePctEncoded)( switch (*first) { case _UT('%'): */ - if (first + 1 >= afterLast) { + if (afterLast - first < 2) { URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; } switch (first[1]) { case URI_SET_HEXDIG: - if (first + 2 >= afterLast) { + if (afterLast - first < 3) { URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; } @@ -2286,12 +2286,10 @@ int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { /* Host data - IPvFuture (may affect host text) */ if (uri->hostData.ipFuture.first != NULL) { - /* NOTE: .hostData.ipFuture may hold the very same range pointers - * as .hostText; then we need to prevent freeing memory twice. */ - if (uri->hostText.first == uri->hostData.ipFuture.first) { - uri->hostText.first = NULL; - uri->hostText.afterLast = NULL; - } + /* NOTE: .hostData.ipFuture holds the very same range pointers + * as .hostText; we must not free memory twice. */ + uri->hostText.first = NULL; + uri->hostText.afterLast = NULL; if (uri->hostData.ipFuture.first != uri->hostData.ipFuture.afterLast) { memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first); @@ -2332,20 +2330,7 @@ int URI_FUNC(FreeUriMembersMm)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { } /* Path */ - if (uri->pathHead != NULL) { - URI_TYPE(PathSegment) * segWalk = uri->pathHead; - while (segWalk != NULL) { - URI_TYPE(PathSegment) * const next = segWalk->next; - if (uri->owner && (segWalk->text.first != NULL) - && (segWalk->text.first < segWalk->text.afterLast)) { - memory->free(memory, (URI_CHAR *)segWalk->text.first); - } - memory->free(memory, segWalk); - segWalk = next; - } - uri->pathHead = NULL; - uri->pathTail = NULL; - } + URI_FUNC(FreeUriPath)(uri, memory); if (uri->owner) { /* Query */ diff --git a/ext/uri/uriparser/src/UriRecompose.c b/ext/uri/uriparser/src/UriRecompose.c index 5027eca6cfa33..1567efc81dcbf 100644 --- a/ext/uri/uriparser/src/UriRecompose.c +++ b/ext/uri/uriparser/src/UriRecompose.c @@ -152,7 +152,7 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, /* [05/19] endif; */ } /* [06/19] if defined(authority) then */ - if (URI_FUNC(IsHostSet)(uri)) { + if (URI_FUNC(HasHost)(uri)) { /* [07/19] append "//" to result; */ if (dest != NULL) { if (written + 2 <= maxChars) { @@ -422,7 +422,7 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, /* [10/19] append path to result; */ /* Slash needed here? */ if (uri->absolutePath || ((uri->pathHead != NULL) - && URI_FUNC(IsHostSet)(uri))) { + && URI_FUNC(HasHost)(uri))) { if (dest != NULL) { if (written + 1 <= maxChars) { memcpy(dest + written, _UT("/"), diff --git a/ext/uri/uriparser/src/UriResolve.c b/ext/uri/uriparser/src/UriResolve.c index 80031a894d437..8e47e6af8c6f9 100644 --- a/ext/uri/uriparser/src/UriResolve.c +++ b/ext/uri/uriparser/src/UriResolve.c @@ -128,7 +128,7 @@ static int URI_FUNC(ResolveAbsolutePathFlag)(URI_TYPE(Uri) * absWork, return URI_ERROR_NULL; } - if (URI_FUNC(IsHostSet)(absWork) && absWork->absolutePath) { + if (URI_FUNC(HasHost)(absWork) && absWork->absolutePath) { /* Empty segment needed, instead? */ if (absWork->pathHead == NULL) { URI_TYPE(PathSegment) * const segment = memory->malloc(memory, sizeof(URI_TYPE(PathSegment))); @@ -203,7 +203,7 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest, /* [06/32] else */ } else { /* [07/32] if defined(R.authority) then */ - if (URI_FUNC(IsHostSet)(relSource)) { + if (URI_FUNC(HasHost)(relSource)) { /* [08/32] T.authority = R.authority; */ if (!URI_FUNC(CopyAuthority)(absDest, relSource, memory)) { return URI_ERROR_MALLOC; diff --git a/ext/uri/uriparser/src/UriSetFragment.c b/ext/uri/uriparser/src/UriSetFragment.c new file mode 100644 index 0000000000000..f2327c1afa4d0 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetFragment.c @@ -0,0 +1,306 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetFragment.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetFragment.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +#endif + + + +#include + + + +#define URI_SET_DIGIT \ + _UT('0'): \ + case _UT('1'): \ + case _UT('2'): \ + case _UT('3'): \ + case _UT('4'): \ + case _UT('5'): \ + case _UT('6'): \ + case _UT('7'): \ + case _UT('8'): \ + case _UT('9') + + + +#define URI_SET_HEX_LETTER_UPPER \ + _UT('A'): \ + case _UT('B'): \ + case _UT('C'): \ + case _UT('D'): \ + case _UT('E'): \ + case _UT('F') + + + +#define URI_SET_HEX_LETTER_LOWER \ + _UT('a'): \ + case _UT('b'): \ + case _UT('c'): \ + case _UT('d'): \ + case _UT('e'): \ + case _UT('f') + + + +#define URI_SET_HEXDIG \ + URI_SET_DIGIT: \ + case URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER + + + +#define URI_SET_ALPHA \ + URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER: \ + case _UT('g'): \ + case _UT('G'): \ + case _UT('h'): \ + case _UT('H'): \ + case _UT('i'): \ + case _UT('I'): \ + case _UT('j'): \ + case _UT('J'): \ + case _UT('k'): \ + case _UT('K'): \ + case _UT('l'): \ + case _UT('L'): \ + case _UT('m'): \ + case _UT('M'): \ + case _UT('n'): \ + case _UT('N'): \ + case _UT('o'): \ + case _UT('O'): \ + case _UT('p'): \ + case _UT('P'): \ + case _UT('q'): \ + case _UT('Q'): \ + case _UT('r'): \ + case _UT('R'): \ + case _UT('s'): \ + case _UT('S'): \ + case _UT('t'): \ + case _UT('T'): \ + case _UT('u'): \ + case _UT('U'): \ + case _UT('v'): \ + case _UT('V'): \ + case _UT('w'): \ + case _UT('W'): \ + case _UT('x'): \ + case _UT('X'): \ + case _UT('y'): \ + case _UT('Y'): \ + case _UT('z'): \ + case _UT('Z') + + + +#define URI_SET_SUB_DELIMS \ + _UT('!'): \ + case _UT('$'): \ + case _UT('&'): \ + case _UT('\''): \ + case _UT('('): \ + case _UT(')'): \ + case _UT('*'): \ + case _UT('+'): \ + case _UT(','): \ + case _UT(';'): \ + case _UT('=') + + + +#define URI_SET_UNRESERVED \ + URI_SET_ALPHA: \ + case URI_SET_DIGIT: \ + case _UT('-'): \ + case _UT('.'): \ + case _UT('_'): \ + case _UT('~') + + + +UriBool URI_FUNC(IsWellFormedFragment)(const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + /* The related part of the grammar in RFC 3986 reads: + * + * fragment = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ + while (first < afterLast) { + switch (first[0]) { + case URI_SET_UNRESERVED: + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + first += 2; + break; + + case URI_SET_SUB_DELIMS: + break; + + /* ":" / "@" and "/" / "?" */ + case _UT(':'): + case _UT('@'): + case _UT('/'): + case _UT('?'): + break; + + default: + return URI_FALSE; + } + + first++; + } + return URI_TRUE; +} + + + +int URI_FUNC(SetFragmentMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Input validation (before making any changes) */ + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + if ((first != NULL) && (URI_FUNC(IsWellFormedFragment)(first, afterLast) == URI_FALSE)) { + return URI_ERROR_SYNTAX; + } + + /* Clear old value */ + if ((uri->owner == URI_TRUE) && (uri->fragment.first != uri->fragment.afterLast)) { + memory->free(memory, (URI_CHAR *)uri->fragment.first); + } + uri->fragment.first = NULL; + uri->fragment.afterLast = NULL; + + /* Already done? */ + if (first == NULL) { + return URI_SUCCESS; + } + + assert(first != NULL); + + /* Ensure owned */ + if (uri->owner == URI_FALSE) { + const int res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value */ + { + URI_TYPE(TextRange) sourceRange; + sourceRange.first = first; + sourceRange.afterLast = afterLast; + + if (URI_FUNC(CopyRangeAsNeeded)(&uri->fragment, &sourceRange, memory) == URI_FALSE) { + return URI_ERROR_MALLOC; + } + } + + return URI_SUCCESS; +} + + + +int URI_FUNC(SetFragment)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetFragmentMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetHostAuto.c b/ext/uri/uriparser/src/UriSetHostAuto.c new file mode 100644 index 0000000000000..66ade6a5365bb --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostAuto.c @@ -0,0 +1,139 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetHostAuto.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetHostAuto.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriSetHostBase.h" +# include "UriSetHostCommon.h" +# include "UriMemory.h" +#endif + + + +#include + + + +int URI_FUNC(SetHostAutoMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + if ((first == NULL) || (first >= afterLast)) { + return URI_FUNC(SetHostRegNameMm)(uri, first, afterLast, memory); + } + + /* Auto-detect type and then apply */ + { + UriHostType hostType; + + /* IPv6 or IPvFuture? */ + if (first[0] == _UT('[')) { + if ((afterLast - first < 2) || (afterLast[-1] != _UT(']'))) { + return URI_ERROR_SYNTAX; + } + + /* Drop the bracket wrap (for InternalSetHostMm call below) */ + first++; + afterLast--; + + if (first >= afterLast) { + return URI_ERROR_SYNTAX; + } + + switch (first[0]) { + case _UT('v'): + case _UT('V'): + hostType = URI_HOST_TYPE_IPFUTURE; + break; + default: + hostType = URI_HOST_TYPE_IP6; + break; + } + /* IPv4? */ + } else if (URI_FUNC(IsWellFormedHostIp4)(first, afterLast)) { + hostType = URI_HOST_TYPE_IP4; + } else { + /* RegName! */ + hostType = URI_HOST_TYPE_REGNAME; + } + + return URI_FUNC(InternalSetHostMm)(uri, hostType, first, afterLast, memory); + } +} + + + +int URI_FUNC(SetHostAuto)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetHostAutoMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetHostBase.h b/ext/uri/uriparser/src/UriSetHostBase.h new file mode 100644 index 0000000000000..79b643cc0c4b0 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostBase.h @@ -0,0 +1,53 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef URI_SET_HOST_BASE_H +#define URI_SET_HOST_BASE_H 1 + + + +typedef enum UriHostTypeEnum { + URI_HOST_TYPE_IP4, + URI_HOST_TYPE_IP6, + URI_HOST_TYPE_IPFUTURE, + URI_HOST_TYPE_REGNAME +} UriHostType; + + + +#endif /* URI_SET_HOST_BASE_H */ diff --git a/ext/uri/uriparser/src/UriSetHostCommon.c b/ext/uri/uriparser/src/UriSetHostCommon.c new file mode 100644 index 0000000000000..343db849dfff2 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostCommon.c @@ -0,0 +1,266 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriSetHostCommon.c + * Holds code used by multiple SetHost* functions. + * NOTE: This source file includes itself twice. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetHostCommon.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetHostCommon.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include +# include "UriCommon.h" +# include "UriMemory.h" +# include "UriSetHostBase.h" +# include "UriSetHostCommon.h" +#endif + + + +#include + + + +int URI_FUNC(InternalSetHostMm)(URI_TYPE(Uri) * uri, + UriHostType hostType, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Superficial input validation (before making any changes) */ + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + /* The RFC 3986 grammar reads: + * authority = [ userinfo "@" ] host [ ":" port ] + * So no user info or port without a host. */ + if (first == NULL) { + if (uri->userInfo.first != NULL) { + return URI_ERROR_SETHOST_USERINFO_SET; + } else if (uri->portText.first != NULL) { + return URI_ERROR_SETHOST_PORT_SET; + } + } + + /* Syntax-check the new value */ + if (first != NULL) { + switch (hostType) { + case URI_HOST_TYPE_IP4: + if (URI_FUNC(IsWellFormedHostIp4)(first, afterLast) == URI_FALSE) { + return URI_ERROR_SYNTAX; + } + break; + case URI_HOST_TYPE_IP6: + { + const int res = URI_FUNC(IsWellFormedHostIp6Mm)(first, afterLast, memory); + assert((res == URI_SUCCESS) || (res == URI_ERROR_SYNTAX) || (res == URI_ERROR_MALLOC)); + if (res != URI_SUCCESS) { + return res; + } + } + break; + case URI_HOST_TYPE_IPFUTURE: + { + const int res = URI_FUNC(IsWellFormedHostIpFutureMm)(first, afterLast, memory); + assert((res == URI_SUCCESS) || (res == URI_ERROR_SYNTAX) || (res == URI_ERROR_MALLOC)); + if (res != URI_SUCCESS) { + return res; + } + } + break; + case URI_HOST_TYPE_REGNAME: + if (URI_FUNC(IsWellFormedHostRegName)(first, afterLast) == URI_FALSE) { + return URI_ERROR_SYNTAX; + } + break; + default: + assert(0 && "Unsupported URI host type"); + } + } + + { + /* Clear old value */ + const UriBool hadHostBefore = URI_FUNC(HasHost)(uri); + if (uri->hostData.ipFuture.first != NULL) { + /* NOTE: .hostData.ipFuture holds the very same range pointers + * as .hostText; we must not free memory twice. */ + uri->hostText.first = NULL; + uri->hostText.afterLast = NULL; + + if ((uri->owner == URI_TRUE) && (uri->hostData.ipFuture.first != uri->hostData.ipFuture.afterLast)) { + memory->free(memory, (URI_CHAR *)uri->hostData.ipFuture.first); + } + uri->hostData.ipFuture.first = NULL; + uri->hostData.ipFuture.afterLast = NULL; + } else if (uri->hostText.first != NULL) { + if ((uri->owner == URI_TRUE) && (uri->hostText.first != uri->hostText.afterLast)) { + memory->free(memory, (URI_CHAR *)uri->hostText.first); + } + uri->hostText.first = NULL; + uri->hostText.afterLast = NULL; + } + + if (uri->hostData.ip4 != NULL) { + memory->free(memory, uri->hostData.ip4); + uri->hostData.ip4 = NULL; + } else if (uri->hostData.ip6 != NULL) { + memory->free(memory, uri->hostData.ip6); + uri->hostData.ip6 = NULL; + } + + /* Already done setting? */ + if (first == NULL) { + /* Yes, but disambiguate as needed */ + if (hadHostBefore == URI_TRUE) { + uri->absolutePath = URI_TRUE; + + { + const UriBool success = URI_FUNC(EnsureThatPathIsNotMistakenForHost)(uri, memory); + return (success == URI_TRUE) + ? URI_SUCCESS + : URI_ERROR_MALLOC; + } + } + + return URI_SUCCESS; + } + } + + assert(first != NULL); + + /* Ensure owned */ + if (uri->owner == URI_FALSE) { + const int res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value; NOTE that .hostText is set for all four host types */ + { + URI_TYPE(TextRange) sourceRange; + sourceRange.first = first; + sourceRange.afterLast = afterLast; + + if (URI_FUNC(CopyRangeAsNeeded)(&uri->hostText, &sourceRange, memory) == URI_FALSE) { + return URI_ERROR_MALLOC; + } + + uri->absolutePath = URI_FALSE; /* always URI_FALSE for URIs with host */ + + /* Fill .hostData as needed */ + switch (hostType) { + case URI_HOST_TYPE_IP4: + { + uri->hostData.ip4 = memory->malloc(memory, sizeof(UriIp4)); + if (uri->hostData.ip4 == NULL) { + return URI_ERROR_MALLOC; + } + + { + const int res = URI_FUNC(ParseIpFourAddress)(uri->hostData.ip4->data, first, afterLast); +#if defined(NDEBUG) + (void)res; /* i.e. mark as unused */ +#else + assert(res == URI_SUCCESS); /* because checked for well-formedness earlier */ +#endif + } + } + break; + case URI_HOST_TYPE_IP6: + { + uri->hostData.ip6 = memory->malloc(memory, sizeof(UriIp6)); + if (uri->hostData.ip6 == NULL) { + return URI_ERROR_MALLOC; + } + + { + const int res = URI_FUNC(ParseIpSixAddressMm)(uri->hostData.ip6, first, afterLast, memory); + assert((res == URI_SUCCESS) || (res == URI_ERROR_MALLOC)); /* because checked for well-formedness earlier */ + if (res != URI_SUCCESS) { + return res; + } + } + } + break; + case URI_HOST_TYPE_IPFUTURE: + uri->hostData.ipFuture.first = uri->hostText.first; + uri->hostData.ipFuture.afterLast = uri->hostText.afterLast; + break; + case URI_HOST_TYPE_REGNAME: + break; + default: + assert(0 && "Unsupported URI host type"); + } + } + + return URI_SUCCESS; +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetHostCommon.h b/ext/uri/uriparser/src/UriSetHostCommon.h new file mode 100644 index 0000000000000..1914d8480eb4a --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostCommon.h @@ -0,0 +1,79 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if (defined(URI_PASS_ANSI) && !defined(URI_SET_HOST_COMMON_H_ANSI)) \ + || (defined(URI_PASS_UNICODE) && !defined(URI_SET_HOST_COMMON_H_UNICODE)) \ + || (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetHostCommon.h" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetHostCommon.h" +# undef URI_PASS_UNICODE +# endif +/* Only one pass for each encoding */ +#elif (defined(URI_PASS_ANSI) && !defined(URI_SET_HOST_COMMON_H_ANSI) \ + && defined(URI_ENABLE_ANSI)) || (defined(URI_PASS_UNICODE) \ + && !defined(URI_SET_HOST_COMMON_H_UNICODE) && defined(URI_ENABLE_UNICODE)) +# ifdef URI_PASS_ANSI +# define URI_SET_HOST_COMMON_H_ANSI 1 +# include +# else +# define URI_SET_HOST_COMMON_H_UNICODE 1 +# include +# endif + + + +int URI_FUNC(InternalSetHostMm)(URI_TYPE(Uri) * uri, + UriHostType hostType, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory); + + + +#endif +#endif diff --git a/ext/uri/uriparser/src/UriSetHostIp4.c b/ext/uri/uriparser/src/UriSetHostIp4.c new file mode 100644 index 0000000000000..e07e249c23d2a --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostIp4.c @@ -0,0 +1,105 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetHostIp4.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetHostIp4.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include +# include "UriMemory.h" +# include "UriSetHostBase.h" +# include "UriSetHostCommon.h" +#endif + + + +UriBool URI_FUNC(IsWellFormedHostIp4)(const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + { + unsigned char octetOutput[4]; + return (URI_FUNC(ParseIpFourAddress)(octetOutput, first, afterLast) == URI_SUCCESS) + ? URI_TRUE + : URI_FALSE; + } +} + + + +int URI_FUNC(SetHostIp4Mm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + return URI_FUNC(InternalSetHostMm)(uri, URI_HOST_TYPE_IP4, first, afterLast, memory); +} + + + +int URI_FUNC(SetHostIp4)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetHostIp4Mm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetHostIp6.c b/ext/uri/uriparser/src/UriSetHostIp6.c new file mode 100644 index 0000000000000..f99365558ff0b --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostIp6.c @@ -0,0 +1,182 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetHostIp6.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetHostIp6.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriMemory.h" +# include "UriSetHostBase.h" +# include "UriSetHostCommon.h" +#endif + + + +#include +#include /* for memcpy */ + + + +#define URI_MAX_IP6_LEN (8 * 4 + 7 * 1) /* i.e. 8 full quads plus 7 colon separators */ + + + +int URI_FUNC(ParseIpSixAddressMm)(UriIp6 * output, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* NOTE: output is allowed to be NULL */ + if ((first == NULL) || (afterLast == NULL)) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + /* Are we dealing with potential IPvFuture input? */ + if (first < afterLast) { + switch (first[0]) { + case _UT('v'): + case _UT('V'): + return URI_ERROR_SYNTAX; + default: + break; + } + } + + /* Are we dealing with IPv6 input? */ + { + /* Assemble "//[..]" input wrap for upcoming parse as a URI + * NOTE: If the input contains closing "]" on its own, the resulting + * string will not be valid URI syntax, and hence there is + * no risk of false positives from "bracket injection". */ + URI_CHAR candidate[3 + URI_MAX_IP6_LEN + 1 + 1] = _UT("//["); + const size_t inputLenChars = (afterLast - first); + + /* Detect overflow */ + if (inputLenChars > URI_MAX_IP6_LEN) { + return URI_ERROR_SYNTAX; + } + + memcpy(candidate + 3, first, inputLenChars * sizeof(URI_CHAR)); + memcpy(candidate + 3 + inputLenChars, _UT("]"), 2 * sizeof(URI_CHAR)); /* includes zero terminator */ + + /* Parse as an RFC 3986 URI */ + { + const size_t candidateLenChars = 3 + inputLenChars + 1; + URI_TYPE(Uri) uri; + const int res = URI_FUNC(ParseSingleUriExMm)(&uri, candidate, candidate + candidateLenChars, NULL, memory); + + assert((res == URI_SUCCESS) || (res == URI_ERROR_SYNTAX) || (res == URI_ERROR_MALLOC)); + + if (res == URI_SUCCESS) { + assert(uri.hostData.ip6 != NULL); + + if (output != NULL) { + memcpy(output->data, uri.hostData.ip6->data, sizeof(output->data)); + } + + URI_FUNC(FreeUriMembersMm)(&uri, memory); + } + + return res; + } + } +} + + + +int URI_FUNC(ParseIpSixAddress)(UriIp6 * output, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(ParseIpSixAddressMm)(output, first, afterLast, NULL); +} + + + +int URI_FUNC(IsWellFormedHostIp6Mm)(const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { + return URI_FUNC(ParseIpSixAddressMm)(NULL, first, afterLast, memory); +} + + + +int URI_FUNC(IsWellFormedHostIp6)(const URI_CHAR * first, const URI_CHAR * afterLast) { + return URI_FUNC(IsWellFormedHostIp6Mm)(first, afterLast, NULL); +} + + + +int URI_FUNC(SetHostIp6Mm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + return URI_FUNC(InternalSetHostMm)(uri, URI_HOST_TYPE_IP6, first, afterLast, memory); +} + + + +int URI_FUNC(SetHostIp6)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetHostIp6Mm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetHostIpFuture.c b/ext/uri/uriparser/src/UriSetHostIpFuture.c new file mode 100644 index 0000000000000..aa84a82f4fe68 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostIpFuture.c @@ -0,0 +1,174 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetHostIpFuture.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetHostIpFuture.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriMemory.h" +# include "UriSetHostBase.h" +# include "UriSetHostCommon.h" +#endif + + + +#include +#include /* for memcpy */ + + + +int URI_FUNC(IsWellFormedHostIpFutureMm)(const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + /* Are we dealing with potential IPv6 input? */ + if (first < afterLast) { + switch (first[0]) { + case _UT('v'): + case _UT('V'): + break; + default: + return URI_ERROR_SYNTAX; + } + } + + /* Are we dealing with IPvFuture input? */ + { + /* Assemble "//[..]" input wrap for upcoming parse as a URI + * NOTE: If the input contains closing "]" on its own, the resulting + * string will not be valid URI syntax, and hence there is + * no risk of false positives from "bracket injection". */ + const size_t inputLenChars = (afterLast - first); + const size_t MAX_SIZE_T = (size_t)-1; + + /* Detect overflow */ + if (MAX_SIZE_T - inputLenChars < 3 + 1 + 1) { + return URI_ERROR_MALLOC; + } + + { + const size_t candidateLenChars = 3 + inputLenChars + 1; + + /* Detect overflow */ + if (MAX_SIZE_T / sizeof(URI_CHAR) < candidateLenChars + 1) { + return URI_ERROR_MALLOC; + } + + { + URI_CHAR * const candidate = memory->malloc(memory, (candidateLenChars + 1) * sizeof(URI_CHAR)); + + if (candidate == NULL) { + return URI_ERROR_MALLOC; + } + + memcpy(candidate, _UT("//["), 3 * sizeof(URI_CHAR)); + memcpy(candidate + 3, first, inputLenChars * sizeof(URI_CHAR)); + memcpy(candidate + 3 + inputLenChars, _UT("]"), 2 * sizeof(URI_CHAR)); /* includes zero terminator */ + + /* Parse as an RFC 3986 URI */ + { + URI_TYPE(Uri) uri; + const int res = URI_FUNC(ParseSingleUriExMm)(&uri, candidate, candidate + candidateLenChars, NULL, memory); + + assert((res == URI_SUCCESS) || (res == URI_ERROR_SYNTAX) || (res == URI_ERROR_MALLOC)); + + if (res == URI_SUCCESS) { + assert(uri.hostData.ipFuture.first != NULL); + URI_FUNC(FreeUriMembersMm)(&uri, memory); + } + + memory->free(memory, candidate); + + return res; + } + } + } + } +} + + + +int URI_FUNC(IsWellFormedHostIpFuture)(const URI_CHAR * first, const URI_CHAR * afterLast) { + return URI_FUNC(IsWellFormedHostIpFutureMm)(first, afterLast, NULL); +} + + + +int URI_FUNC(SetHostIpFutureMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + return URI_FUNC(InternalSetHostMm)(uri, URI_HOST_TYPE_IPFUTURE, first, afterLast, memory); +} + + + +int URI_FUNC(SetHostIpFuture)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetHostIpFutureMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetHostRegName.c b/ext/uri/uriparser/src/UriSetHostRegName.c new file mode 100644 index 0000000000000..d09e2e98e3616 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetHostRegName.c @@ -0,0 +1,246 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetHostRegName.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetHostRegName.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriMemory.h" +# include "UriSetHostBase.h" +# include "UriSetHostCommon.h" +#endif + + + +#define URI_SET_DIGIT \ + _UT('0'): \ + case _UT('1'): \ + case _UT('2'): \ + case _UT('3'): \ + case _UT('4'): \ + case _UT('5'): \ + case _UT('6'): \ + case _UT('7'): \ + case _UT('8'): \ + case _UT('9') + + + +#define URI_SET_HEX_LETTER_UPPER \ + _UT('A'): \ + case _UT('B'): \ + case _UT('C'): \ + case _UT('D'): \ + case _UT('E'): \ + case _UT('F') + + + +#define URI_SET_HEX_LETTER_LOWER \ + _UT('a'): \ + case _UT('b'): \ + case _UT('c'): \ + case _UT('d'): \ + case _UT('e'): \ + case _UT('f') + + + +#define URI_SET_HEXDIG \ + URI_SET_DIGIT: \ + case URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER + + + +#define URI_SET_ALPHA \ + URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER: \ + case _UT('g'): \ + case _UT('G'): \ + case _UT('h'): \ + case _UT('H'): \ + case _UT('i'): \ + case _UT('I'): \ + case _UT('j'): \ + case _UT('J'): \ + case _UT('k'): \ + case _UT('K'): \ + case _UT('l'): \ + case _UT('L'): \ + case _UT('m'): \ + case _UT('M'): \ + case _UT('n'): \ + case _UT('N'): \ + case _UT('o'): \ + case _UT('O'): \ + case _UT('p'): \ + case _UT('P'): \ + case _UT('q'): \ + case _UT('Q'): \ + case _UT('r'): \ + case _UT('R'): \ + case _UT('s'): \ + case _UT('S'): \ + case _UT('t'): \ + case _UT('T'): \ + case _UT('u'): \ + case _UT('U'): \ + case _UT('v'): \ + case _UT('V'): \ + case _UT('w'): \ + case _UT('W'): \ + case _UT('x'): \ + case _UT('X'): \ + case _UT('y'): \ + case _UT('Y'): \ + case _UT('z'): \ + case _UT('Z') + + + +#define URI_SET_SUB_DELIMS \ + _UT('!'): \ + case _UT('$'): \ + case _UT('&'): \ + case _UT('\''): \ + case _UT('('): \ + case _UT(')'): \ + case _UT('*'): \ + case _UT('+'): \ + case _UT(','): \ + case _UT(';'): \ + case _UT('=') + + + +#define URI_SET_UNRESERVED \ + URI_SET_ALPHA: \ + case URI_SET_DIGIT: \ + case _UT('-'): \ + case _UT('.'): \ + case _UT('_'): \ + case _UT('~') + + + +UriBool URI_FUNC(IsWellFormedHostRegName)(const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + /* reg-name = *( unreserved / pct-encoded / sub-delims ) */ + while (first < afterLast) { + switch (first[0]) { + case URI_SET_UNRESERVED: + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + first += 2; + break; + + case URI_SET_SUB_DELIMS: + break; + + default: + return URI_FALSE; + } + + first++; + } + return URI_TRUE; +} + + + +int URI_FUNC(SetHostRegNameMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + return URI_FUNC(InternalSetHostMm)(uri, URI_HOST_TYPE_REGNAME, first, afterLast, memory); +} + + + +int URI_FUNC(SetHostRegName)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetHostRegNameMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetPath.c b/ext/uri/uriparser/src/UriSetPath.c new file mode 100644 index 0000000000000..abd783b3c65ae --- /dev/null +++ b/ext/uri/uriparser/src/UriSetPath.c @@ -0,0 +1,495 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetPath.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetPath.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +#endif + + + +#include + + + +#define URI_SET_DIGIT \ + _UT('0'): \ + case _UT('1'): \ + case _UT('2'): \ + case _UT('3'): \ + case _UT('4'): \ + case _UT('5'): \ + case _UT('6'): \ + case _UT('7'): \ + case _UT('8'): \ + case _UT('9') + + + +#define URI_SET_HEX_LETTER_UPPER \ + _UT('A'): \ + case _UT('B'): \ + case _UT('C'): \ + case _UT('D'): \ + case _UT('E'): \ + case _UT('F') + + + +#define URI_SET_HEX_LETTER_LOWER \ + _UT('a'): \ + case _UT('b'): \ + case _UT('c'): \ + case _UT('d'): \ + case _UT('e'): \ + case _UT('f') + + + +#define URI_SET_HEXDIG \ + URI_SET_DIGIT: \ + case URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER + + + +#define URI_SET_ALPHA \ + URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER: \ + case _UT('g'): \ + case _UT('G'): \ + case _UT('h'): \ + case _UT('H'): \ + case _UT('i'): \ + case _UT('I'): \ + case _UT('j'): \ + case _UT('J'): \ + case _UT('k'): \ + case _UT('K'): \ + case _UT('l'): \ + case _UT('L'): \ + case _UT('m'): \ + case _UT('M'): \ + case _UT('n'): \ + case _UT('N'): \ + case _UT('o'): \ + case _UT('O'): \ + case _UT('p'): \ + case _UT('P'): \ + case _UT('q'): \ + case _UT('Q'): \ + case _UT('r'): \ + case _UT('R'): \ + case _UT('s'): \ + case _UT('S'): \ + case _UT('t'): \ + case _UT('T'): \ + case _UT('u'): \ + case _UT('U'): \ + case _UT('v'): \ + case _UT('V'): \ + case _UT('w'): \ + case _UT('W'): \ + case _UT('x'): \ + case _UT('X'): \ + case _UT('y'): \ + case _UT('Y'): \ + case _UT('z'): \ + case _UT('Z') + + + +#define URI_SET_SUB_DELIMS \ + _UT('!'): \ + case _UT('$'): \ + case _UT('&'): \ + case _UT('\''): \ + case _UT('('): \ + case _UT(')'): \ + case _UT('*'): \ + case _UT('+'): \ + case _UT(','): \ + case _UT(';'): \ + case _UT('=') + + + +#define URI_SET_UNRESERVED \ + URI_SET_ALPHA: \ + case URI_SET_DIGIT: \ + case _UT('-'): \ + case _UT('.'): \ + case _UT('_'): \ + case _UT('~') + + + +UriBool URI_FUNC(IsWellFormedPath)(const URI_CHAR * first, const URI_CHAR * afterLast, UriBool hasHost) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + if ((hasHost == URI_TRUE) && ((first >= afterLast) || (first[0] != _UT('/')))) { + return URI_FALSE; + } + + /* The related part of the grammar in RFC 3986 (section 3.3) reads: + * + * path = path-abempty ; begins with "/" or is empty + * / path-absolute ; begins with "/" but not "//" + * / path-noscheme ; begins with a non-colon segment + * / path-rootless ; begins with a segment + * / path-empty ; zero characters + * + * path-abempty = *( "/" segment ) + * path-absolute = "/" [ segment-nz *( "/" segment ) ] + * path-noscheme = segment-nz-nc *( "/" segment ) + * path-rootless = segment-nz *( "/" segment ) + * path-empty = 0 + * + * segment = *pchar + * segment-nz = 1*pchar + * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + * ; non-zero-length segment without any colon ":" + * + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * + * The check below simplifies this to .. + * + * path = *( unreserved / pct-encoded / sub-delims / ":" / "@" / "/" ) + * + * .. and leaves the rest to pre-return removal of ambiguity + * from cases like "path1:/path2" and "//path1/path2" inside SetPath. + */ + while (first < afterLast) { + switch (first[0]) { + case URI_SET_UNRESERVED: + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + first += 2; + break; + + case URI_SET_SUB_DELIMS: + break; + + /* ":" / "@" and "/" */ + case _UT(':'): + case _UT('@'): + case _UT('/'): + break; + + default: + return URI_FALSE; + } + + first++; + } + return URI_TRUE; +} + + + +static void URI_FUNC(DropEmptyFirstPathSegment)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { + assert(uri != NULL); + assert(memory != NULL); + assert(uri->pathHead != NULL); + assert(uri->pathHead->text.first == uri->pathHead->text.afterLast); + + { + URI_TYPE(PathSegment) * const originalHead = uri->pathHead; + + uri->pathHead = uri->pathHead->next; + + originalHead->text.first = NULL; + originalHead->text.afterLast = NULL; + memory->free(memory, originalHead); + } +} + + + +/* URIs without a host encode a leading slash in the path as .absolutePath == URI_TRUE. + * This function checks for a leading empty path segment (that would have the "visual effect" + * of a leading slash during stringification) and transforms it into .absolutePath == URI_TRUE + * instead, if present. */ +static void URI_FUNC(TransformEmptyLeadPathSegments)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { + assert(uri != NULL); + assert(memory != NULL); + + if ((URI_FUNC(HasHost)(uri) == URI_TRUE) + || (uri->pathHead == NULL) + || (uri->pathHead->text.first != uri->pathHead->text.afterLast)) { + return; /* i.e. nothing to do */ + } + + assert(uri->absolutePath == URI_FALSE); + + URI_FUNC(DropEmptyFirstPathSegment)(uri, memory); + + uri->absolutePath = URI_TRUE; +} + + + +static int URI_FUNC(InternalSetPath)(URI_TYPE(Uri) * destUri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + assert(destUri != NULL); + assert(first != NULL); + assert(afterLast != NULL); + assert(memory != NULL); + assert(destUri->pathHead == NULL); /* set by SetPathMm right before */ + assert(destUri->pathTail == NULL); /* set by SetPathMm right before */ + assert(destUri->absolutePath == URI_FALSE); /* set by SetPathMm right before */ + + /* Skip the leading slash from target URIs with a host (so that we can + * transfer the path 1:1 further down) */ + if (URI_FUNC(HasHost)(destUri) == URI_TRUE) { + /* NOTE: This is because SetPathMm called IsWellFormedPath earlier: */ + assert((afterLast - first >= 1) && (first[0] == _UT('/'))); + first++; + } else if (first == afterLast) { + /* This avoids (1) all the expensive but unnecessary work below + * and also (2) mis-encoding as single empty path segment + * that would need (detection and) repair further down otherwise */ + return URI_SUCCESS; + } + + /* Assemble "///.." input wrap for upcoming parse as a URI */ + { + const size_t inputLenChars = (afterLast - first); + const size_t MAX_SIZE_T = (size_t)-1; + + /* Detect overflow */ + if (MAX_SIZE_T - inputLenChars < 3 + 1) { + return URI_ERROR_MALLOC; + } + + { + const size_t candidateLenChars = 3 + inputLenChars; + + /* Detect overflow */ + if (MAX_SIZE_T / sizeof(URI_CHAR) < candidateLenChars + 1) { + return URI_ERROR_MALLOC; + } + + { + URI_CHAR * const candidate = memory->malloc(memory, (candidateLenChars + 1) * sizeof(URI_CHAR)); + + if (candidate == NULL) { + return URI_ERROR_MALLOC; + } + + memcpy(candidate, _UT("///"), 3 * sizeof(URI_CHAR)); + memcpy(candidate + 3, first, inputLenChars * sizeof(URI_CHAR)); + candidate[3 + inputLenChars] = _UT('\0'); + + /* Parse as an RFC 3986 URI */ + { + URI_TYPE(Uri) tempUri; + const int res = URI_FUNC(ParseSingleUriExMm)(&tempUri, + candidate, + candidate + candidateLenChars, + NULL, + memory); + assert((res == URI_SUCCESS) || (res == URI_ERROR_SYNTAX) || (res == URI_ERROR_MALLOC)); + if (res != URI_SUCCESS) { + memory->free(memory, candidate); + return res; + } + + /* Nothing but path and host is supposed to be set by the parse, in particular not: */ + assert(tempUri.query.first == NULL); + assert(tempUri.fragment.first == NULL); + + /* Ensure that the strings in the path segments are all owned by `tempUri` + * because we want to (1) rip out and keep the full path list further down + * and (2) be able to free the parsed string (`candidate`) also. */ + { + const int res = URI_FUNC(MakeOwnerMm)(&tempUri, memory); + assert((res == URI_SUCCESS) || (res == URI_ERROR_MALLOC)); + if (res != URI_SUCCESS) { + URI_FUNC(FreeUriMembersMm)(&tempUri, memory); + memory->free(memory, candidate); + return res; + } + assert(tempUri.owner == URI_TRUE); + } + + /* Move path to destination URI */ + assert(tempUri.absolutePath == URI_FALSE); /* always URI_FALSE for URIs with host */ + destUri->pathHead = tempUri.pathHead; + destUri->pathTail = tempUri.pathTail; + destUri->absolutePath = URI_FALSE; + + tempUri.pathHead = NULL; + tempUri.pathTail = NULL; + + /* Free the rest of the temp URI */ + URI_FUNC(FreeUriMembersMm)(&tempUri, memory); + memory->free(memory, candidate); + + /* Restore use of .absolutePath as needed */ + URI_FUNC(TransformEmptyLeadPathSegments)(destUri, memory); + + /* Disambiguate as needed */ + { + const UriBool success = URI_FUNC(FixPathNoScheme)(destUri, memory); + if (success == URI_FALSE) { + return URI_ERROR_MALLOC; + } + } + { + const UriBool success = URI_FUNC(EnsureThatPathIsNotMistakenForHost)(destUri, memory); + if (success == URI_FALSE) { + return URI_ERROR_MALLOC; + } + } + } + } + } + } + + return URI_SUCCESS; +} + + + +int URI_FUNC(SetPathMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Input validation (before making any changes) */ + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + if ((first != NULL) && (URI_FUNC(IsWellFormedPath)(first, afterLast, URI_FUNC(HasHost)(uri)) == URI_FALSE)) { + return URI_ERROR_SYNTAX; + } + + /* Clear old value */ + { + const int res = URI_FUNC(FreeUriPath)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + uri->absolutePath = URI_FALSE; + } + + /* Already done? */ + if (first == NULL) { + return URI_SUCCESS; + } + + assert(first != NULL); + + /* Ensure owned */ + if (uri->owner == URI_FALSE) { + const int res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value */ + { + const int res = URI_FUNC(InternalSetPath)(uri, first, afterLast, memory); + assert((res == URI_SUCCESS) || (res == URI_ERROR_SYNTAX) || (res == URI_ERROR_MALLOC)); + return res; + } +} + + + +int URI_FUNC(SetPath)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetPathMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetPort.c b/ext/uri/uriparser/src/UriSetPort.c new file mode 100644 index 0000000000000..3331b717e21e7 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetPort.c @@ -0,0 +1,179 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetPort.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetPort.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +#endif + + + +#include + + + +#define URI_SET_DIGIT \ + _UT('0'): \ + case _UT('1'): \ + case _UT('2'): \ + case _UT('3'): \ + case _UT('4'): \ + case _UT('5'): \ + case _UT('6'): \ + case _UT('7'): \ + case _UT('8'): \ + case _UT('9') + + + +UriBool URI_FUNC(IsWellFormedPort)(const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + /* NOTE: Grammar reads "port = *DIGIT" which includes the empty string. */ + while (first < afterLast) { + switch (first[0]) { + case URI_SET_DIGIT: + break; + default: + return URI_FALSE; + } + first++; + } + return URI_TRUE; +} + + + +int URI_FUNC(SetPortTextMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Input validation (before making any changes) */ + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + /* The RFC 3986 grammar reads: + * authority = [ userinfo "@" ] host [ ":" port ] + * So no port without a host. */ + if ((first != NULL) && (URI_FUNC(HasHost)(uri) == URI_FALSE)) { + return URI_ERROR_SETPORT_HOST_NOT_SET; + } + + if ((first != NULL) && (URI_FUNC(IsWellFormedPort)(first, afterLast) == URI_FALSE)) { + return URI_ERROR_SYNTAX; + } + + /* Clear old value */ + if ((uri->owner == URI_TRUE) && (uri->portText.first != uri->portText.afterLast)) { + memory->free(memory, (URI_CHAR *)uri->portText.first); + } + uri->portText.first = NULL; + uri->portText.afterLast = NULL; + + /* Already done? */ + if (first == NULL) { + return URI_SUCCESS; + } + + assert(first != NULL); + + /* Ensure owned */ + if (uri->owner == URI_FALSE) { + const int res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value */ + { + URI_TYPE(TextRange) sourceRange; + sourceRange.first = first; + sourceRange.afterLast = afterLast; + + if (URI_FUNC(CopyRangeAsNeeded)(&uri->portText, &sourceRange, memory) == URI_FALSE) { + return URI_ERROR_MALLOC; + } + } + + return URI_SUCCESS; +} + + + +int URI_FUNC(SetPortText)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetPortTextMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetQuery.c b/ext/uri/uriparser/src/UriSetQuery.c new file mode 100644 index 0000000000000..567ff6d1d8aa7 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetQuery.c @@ -0,0 +1,306 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetQuery.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetQuery.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +#endif + + + +#include + + + +#define URI_SET_DIGIT \ + _UT('0'): \ + case _UT('1'): \ + case _UT('2'): \ + case _UT('3'): \ + case _UT('4'): \ + case _UT('5'): \ + case _UT('6'): \ + case _UT('7'): \ + case _UT('8'): \ + case _UT('9') + + + +#define URI_SET_HEX_LETTER_UPPER \ + _UT('A'): \ + case _UT('B'): \ + case _UT('C'): \ + case _UT('D'): \ + case _UT('E'): \ + case _UT('F') + + + +#define URI_SET_HEX_LETTER_LOWER \ + _UT('a'): \ + case _UT('b'): \ + case _UT('c'): \ + case _UT('d'): \ + case _UT('e'): \ + case _UT('f') + + + +#define URI_SET_HEXDIG \ + URI_SET_DIGIT: \ + case URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER + + + +#define URI_SET_ALPHA \ + URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER: \ + case _UT('g'): \ + case _UT('G'): \ + case _UT('h'): \ + case _UT('H'): \ + case _UT('i'): \ + case _UT('I'): \ + case _UT('j'): \ + case _UT('J'): \ + case _UT('k'): \ + case _UT('K'): \ + case _UT('l'): \ + case _UT('L'): \ + case _UT('m'): \ + case _UT('M'): \ + case _UT('n'): \ + case _UT('N'): \ + case _UT('o'): \ + case _UT('O'): \ + case _UT('p'): \ + case _UT('P'): \ + case _UT('q'): \ + case _UT('Q'): \ + case _UT('r'): \ + case _UT('R'): \ + case _UT('s'): \ + case _UT('S'): \ + case _UT('t'): \ + case _UT('T'): \ + case _UT('u'): \ + case _UT('U'): \ + case _UT('v'): \ + case _UT('V'): \ + case _UT('w'): \ + case _UT('W'): \ + case _UT('x'): \ + case _UT('X'): \ + case _UT('y'): \ + case _UT('Y'): \ + case _UT('z'): \ + case _UT('Z') + + + +#define URI_SET_SUB_DELIMS \ + _UT('!'): \ + case _UT('$'): \ + case _UT('&'): \ + case _UT('\''): \ + case _UT('('): \ + case _UT(')'): \ + case _UT('*'): \ + case _UT('+'): \ + case _UT(','): \ + case _UT(';'): \ + case _UT('=') + + + +#define URI_SET_UNRESERVED \ + URI_SET_ALPHA: \ + case URI_SET_DIGIT: \ + case _UT('-'): \ + case _UT('.'): \ + case _UT('_'): \ + case _UT('~') + + + +UriBool URI_FUNC(IsWellFormedQuery)(const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + /* The related part of the grammar in RFC 3986 reads: + * + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ + while (first < afterLast) { + switch (first[0]) { + case URI_SET_UNRESERVED: + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + first += 2; + break; + + case URI_SET_SUB_DELIMS: + break; + + /* ":" / "@" and "/" / "?" */ + case _UT(':'): + case _UT('@'): + case _UT('/'): + case _UT('?'): + break; + + default: + return URI_FALSE; + } + + first++; + } + return URI_TRUE; +} + + + +int URI_FUNC(SetQueryMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Input validation (before making any changes) */ + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + if ((first != NULL) && (URI_FUNC(IsWellFormedQuery)(first, afterLast) == URI_FALSE)) { + return URI_ERROR_SYNTAX; + } + + /* Clear old value */ + if ((uri->owner == URI_TRUE) && (uri->query.first != uri->query.afterLast)) { + memory->free(memory, (URI_CHAR *)uri->query.first); + } + uri->query.first = NULL; + uri->query.afterLast = NULL; + + /* Already done? */ + if (first == NULL) { + return URI_SUCCESS; + } + + assert(first != NULL); + + /* Ensure owned */ + if (uri->owner == URI_FALSE) { + const int res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value */ + { + URI_TYPE(TextRange) sourceRange; + sourceRange.first = first; + sourceRange.afterLast = afterLast; + + if (URI_FUNC(CopyRangeAsNeeded)(&uri->query, &sourceRange, memory) == URI_FALSE) { + return URI_ERROR_MALLOC; + } + } + + return URI_SUCCESS; +} + + + +int URI_FUNC(SetQuery)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetQueryMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetScheme.c b/ext/uri/uriparser/src/UriSetScheme.c new file mode 100644 index 0000000000000..73a75b82350fd --- /dev/null +++ b/ext/uri/uriparser/src/UriSetScheme.c @@ -0,0 +1,272 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetScheme.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetScheme.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +#endif + + + +#include + + + +#define URI_SET_DIGIT \ + _UT('0'): \ + case _UT('1'): \ + case _UT('2'): \ + case _UT('3'): \ + case _UT('4'): \ + case _UT('5'): \ + case _UT('6'): \ + case _UT('7'): \ + case _UT('8'): \ + case _UT('9') + + + +#define URI_SET_HEX_LETTER_UPPER \ + _UT('A'): \ + case _UT('B'): \ + case _UT('C'): \ + case _UT('D'): \ + case _UT('E'): \ + case _UT('F') + + + +#define URI_SET_HEX_LETTER_LOWER \ + _UT('a'): \ + case _UT('b'): \ + case _UT('c'): \ + case _UT('d'): \ + case _UT('e'): \ + case _UT('f') + + + +#define URI_SET_HEXDIG \ + URI_SET_DIGIT: \ + case URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER + + + +#define URI_SET_ALPHA \ + URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER: \ + case _UT('g'): \ + case _UT('G'): \ + case _UT('h'): \ + case _UT('H'): \ + case _UT('i'): \ + case _UT('I'): \ + case _UT('j'): \ + case _UT('J'): \ + case _UT('k'): \ + case _UT('K'): \ + case _UT('l'): \ + case _UT('L'): \ + case _UT('m'): \ + case _UT('M'): \ + case _UT('n'): \ + case _UT('N'): \ + case _UT('o'): \ + case _UT('O'): \ + case _UT('p'): \ + case _UT('P'): \ + case _UT('q'): \ + case _UT('Q'): \ + case _UT('r'): \ + case _UT('R'): \ + case _UT('s'): \ + case _UT('S'): \ + case _UT('t'): \ + case _UT('T'): \ + case _UT('u'): \ + case _UT('U'): \ + case _UT('v'): \ + case _UT('V'): \ + case _UT('w'): \ + case _UT('W'): \ + case _UT('x'): \ + case _UT('X'): \ + case _UT('y'): \ + case _UT('Y'): \ + case _UT('z'): \ + case _UT('Z') + + + +UriBool URI_FUNC(IsWellFormedScheme)(const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + /* The related part of the grammar in RFC 3986 reads: + * + * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + */ + if (first >= afterLast) { + return URI_FALSE; + } + + switch (first[0]) { + case URI_SET_ALPHA: + break; + + default: + return URI_FALSE; + } + + first++; + + while (first < afterLast) { + switch (first[0]) { + case URI_SET_ALPHA: + case URI_SET_DIGIT: + case _UT('+'): + case _UT('-'): + case _UT('.'): + break; + + default: + return URI_FALSE; + } + + first++; + } + return URI_TRUE; +} + + + +int URI_FUNC(SetSchemeMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Input validation (before making any changes) */ + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + if ((first != NULL) && (URI_FUNC(IsWellFormedScheme)(first, afterLast) == URI_FALSE)) { + return URI_ERROR_SYNTAX; + } + + /* Clear old value */ + if ((uri->owner == URI_TRUE) && (uri->scheme.first != uri->scheme.afterLast)) { + memory->free(memory, (URI_CHAR *)uri->scheme.first); + } + uri->scheme.first = NULL; + uri->scheme.afterLast = NULL; + + /* Already done setting? */ + if (first == NULL) { + /* Yes, but disambiguate as needed */ + const UriBool success = URI_FUNC(FixPathNoScheme)(uri, memory); + return (success == URI_TRUE) + ? URI_SUCCESS + : URI_ERROR_MALLOC; + } + + assert(first != NULL); + + /* Ensure owned */ + if (uri->owner == URI_FALSE) { + const int res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value */ + { + URI_TYPE(TextRange) sourceRange; + sourceRange.first = first; + sourceRange.afterLast = afterLast; + + if (URI_FUNC(CopyRangeAsNeeded)(&uri->scheme, &sourceRange, memory) == URI_FALSE) { + return URI_ERROR_MALLOC; + } + } + + return URI_SUCCESS; +} + + + +int URI_FUNC(SetScheme)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetSchemeMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriSetUserInfo.c b/ext/uri/uriparser/src/UriSetUserInfo.c new file mode 100644 index 0000000000000..d30f984395a24 --- /dev/null +++ b/ext/uri/uriparser/src/UriSetUserInfo.c @@ -0,0 +1,306 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriSetUserInfo.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriSetUserInfo.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +# include "UriCommon.h" +# include "UriMemory.h" +#endif + + + +#include + + + +#define URI_SET_DIGIT \ + _UT('0'): \ + case _UT('1'): \ + case _UT('2'): \ + case _UT('3'): \ + case _UT('4'): \ + case _UT('5'): \ + case _UT('6'): \ + case _UT('7'): \ + case _UT('8'): \ + case _UT('9') + + + +#define URI_SET_HEX_LETTER_UPPER \ + _UT('A'): \ + case _UT('B'): \ + case _UT('C'): \ + case _UT('D'): \ + case _UT('E'): \ + case _UT('F') + + + +#define URI_SET_HEX_LETTER_LOWER \ + _UT('a'): \ + case _UT('b'): \ + case _UT('c'): \ + case _UT('d'): \ + case _UT('e'): \ + case _UT('f') + + + +#define URI_SET_HEXDIG \ + URI_SET_DIGIT: \ + case URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER + + + +#define URI_SET_ALPHA \ + URI_SET_HEX_LETTER_UPPER: \ + case URI_SET_HEX_LETTER_LOWER: \ + case _UT('g'): \ + case _UT('G'): \ + case _UT('h'): \ + case _UT('H'): \ + case _UT('i'): \ + case _UT('I'): \ + case _UT('j'): \ + case _UT('J'): \ + case _UT('k'): \ + case _UT('K'): \ + case _UT('l'): \ + case _UT('L'): \ + case _UT('m'): \ + case _UT('M'): \ + case _UT('n'): \ + case _UT('N'): \ + case _UT('o'): \ + case _UT('O'): \ + case _UT('p'): \ + case _UT('P'): \ + case _UT('q'): \ + case _UT('Q'): \ + case _UT('r'): \ + case _UT('R'): \ + case _UT('s'): \ + case _UT('S'): \ + case _UT('t'): \ + case _UT('T'): \ + case _UT('u'): \ + case _UT('U'): \ + case _UT('v'): \ + case _UT('V'): \ + case _UT('w'): \ + case _UT('W'): \ + case _UT('x'): \ + case _UT('X'): \ + case _UT('y'): \ + case _UT('Y'): \ + case _UT('z'): \ + case _UT('Z') + + + +#define URI_SET_SUB_DELIMS \ + _UT('!'): \ + case _UT('$'): \ + case _UT('&'): \ + case _UT('\''): \ + case _UT('('): \ + case _UT(')'): \ + case _UT('*'): \ + case _UT('+'): \ + case _UT(','): \ + case _UT(';'): \ + case _UT('=') + + + +#define URI_SET_UNRESERVED \ + URI_SET_ALPHA: \ + case URI_SET_DIGIT: \ + case _UT('-'): \ + case _UT('.'): \ + case _UT('_'): \ + case _UT('~') + + + +UriBool URI_FUNC(IsWellFormedUserInfo)(const URI_CHAR * first, const URI_CHAR * afterLast) { + if ((first == NULL) || (afterLast == NULL)) { + return URI_FALSE; + } + + /* userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) */ + while (first < afterLast) { + switch (first[0]) { + case URI_SET_UNRESERVED: + break; + + /* pct-encoded */ + case _UT('%'): + if (afterLast - first < 3) { + return URI_FALSE; + } + switch (first[1]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + switch (first[2]) { + case URI_SET_HEXDIG: + break; + default: + return URI_FALSE; + } + first += 2; + break; + + case URI_SET_SUB_DELIMS: + break; + + /* ":" */ + case _UT(':'): + break; + + default: + return URI_FALSE; + } + + first++; + } + return URI_TRUE; +} + + + +int URI_FUNC(SetUserInfoMm)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast, + UriMemoryManager * memory) { + /* Input validation (before making any changes) */ + if ((uri == NULL) || ((first == NULL) != (afterLast == NULL))) { + return URI_ERROR_NULL; + } + + URI_CHECK_MEMORY_MANAGER(memory); /* may return */ + + /* The RFC 3986 grammar reads: + * authority = [ userinfo "@" ] host [ ":" port ] + * So no user info without a host. */ + if ((first != NULL) && (URI_FUNC(HasHost)(uri) == URI_FALSE)) { + return URI_ERROR_SETUSERINFO_HOST_NOT_SET; + } + + if ((first != NULL) && (URI_FUNC(IsWellFormedUserInfo)(first, afterLast) == URI_FALSE)) { + return URI_ERROR_SYNTAX; + } + + /* Clear old value */ + if ((uri->owner == URI_TRUE) && (uri->userInfo.first != uri->userInfo.afterLast)) { + memory->free(memory, (URI_CHAR *)uri->userInfo.first); + } + uri->userInfo.first = NULL; + uri->userInfo.afterLast = NULL; + + /* Already done? */ + if (first == NULL) { + return URI_SUCCESS; + } + + assert(first != NULL); + + /* Ensure owned */ + if (uri->owner == URI_FALSE) { + const int res = URI_FUNC(MakeOwnerMm)(uri, memory); + if (res != URI_SUCCESS) { + return res; + } + } + + assert(uri->owner == URI_TRUE); + + /* Apply new value */ + { + URI_TYPE(TextRange) sourceRange; + sourceRange.first = first; + sourceRange.afterLast = afterLast; + + if (URI_FUNC(CopyRangeAsNeeded)(&uri->userInfo, &sourceRange, memory) == URI_FALSE) { + return URI_ERROR_MALLOC; + } + } + + return URI_SUCCESS; +} + + + +int URI_FUNC(SetUserInfo)(URI_TYPE(Uri) * uri, + const URI_CHAR * first, + const URI_CHAR * afterLast) { + return URI_FUNC(SetUserInfoMm)(uri, first, afterLast, NULL); +} + + + +#endif diff --git a/ext/uri/uriparser/src/UriVersion.c b/ext/uri/uriparser/src/UriVersion.c new file mode 100644 index 0000000000000..81295ca942b31 --- /dev/null +++ b/ext/uri/uriparser/src/UriVersion.c @@ -0,0 +1,87 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriVersion.c + * Implements a runtime version getter. + * NOTE: This source file includes itself twice. + */ + +/* What encodings are enabled? */ +#include +#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE)) +/* Include SELF twice */ +# ifdef URI_ENABLE_ANSI +# define URI_PASS_ANSI 1 +# include "UriVersion.c" +# undef URI_PASS_ANSI +# endif +# ifdef URI_ENABLE_UNICODE +# define URI_PASS_UNICODE 1 +# include "UriVersion.c" +# undef URI_PASS_UNICODE +# endif +#else +# ifdef URI_PASS_ANSI +# include +# else +# include +# include +# endif + + + +#ifndef URI_DOXYGEN +# include +#endif + + + +const URI_CHAR * URI_FUNC(BaseRuntimeVersion)(void) { +#if defined(URI_PASS_ANSI) + return URI_VER_ANSI; +#elif defined(URI_PASS_UNICODE) + return URI_VER_UNICODE; +#else +# error Either URI_PASS_ANSI or URI_PASS_UNICODE must be defined +#endif +} + + + +#endif diff --git a/ext/xml/compat.c b/ext/xml/compat.c index cafb19c2c1edd..ea72a958006e2 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -355,7 +355,9 @@ get_entity(void *user, const xmlChar *name) if (ret == NULL) ret = xmlGetDocEntity(parser->parser->myDoc, name); + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") if (ret == NULL || parser->parser->instate == XML_PARSER_CONTENT) { + ZEND_DIAGNOSTIC_IGNORED_END if (ret == NULL || ret->etype == XML_INTERNAL_GENERAL_ENTITY || ret->etype == XML_INTERNAL_PARAMETER_ENTITY || ret->etype == XML_INTERNAL_PREDEFINED_ENTITY) { /* Predefined entities will expand unless no cdata handler is present */ if (parser->h_default && ! (ret && ret->etype == XML_INTERNAL_PREDEFINED_ENTITY && parser->h_cdata)) { diff --git a/ext/xml/tests/bug25666.phpt b/ext/xml/tests/bug25666.phpt index 54103e0c21007..8de45a78e2a0f 100644 --- a/ext/xml/tests/bug25666.phpt +++ b/ext/xml/tests/bug25666.phpt @@ -28,7 +28,6 @@ $parser = xml_parser_create_ns("ISO-8859-1","@"); xml_set_element_handler($parser,'start_elem','end_elem'); xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); xml_parse($parser, $xml); -xml_parser_free($parser); ?> --EXPECT-- string(24) "http://example.com/foo@a" diff --git a/ext/xml/tests/bug26528.phpt b/ext/xml/tests/bug26528.phpt index c100f481bc836..da5dc64f9077a 100644 --- a/ext/xml/tests/bug26528.phpt +++ b/ext/xml/tests/bug26528.phpt @@ -7,7 +7,6 @@ xml $sample = ""; $parser = xml_parser_create(); $res = xml_parse_into_struct($parser,$sample,$vals,$index); - xml_parser_free($parser); var_dump($vals); ?> --EXPECT-- diff --git a/ext/xml/tests/bug26614.inc b/ext/xml/tests/bug26614.inc index 1b0c94edb9fbe..c8050e54c77c8 100644 --- a/ext/xml/tests/bug26614.inc +++ b/ext/xml/tests/bug26614.inc @@ -69,5 +69,4 @@ foreach ($xmls as $desc => $xml) { xml_set_character_data_handler($xml_parser, "characterData"); if (!xml_parse($xml_parser, $xml, true)) echo "Error: ".xml_error_string(xml_get_error_code($xml_parser))."\n"; - xml_parser_free($xml_parser); } diff --git a/ext/xml/tests/bug27908.phpt b/ext/xml/tests/bug27908.phpt index fee8cfb1ee4a6..e071d531092ec 100644 --- a/ext/xml/tests/bug27908.phpt +++ b/ext/xml/tests/bug27908.phpt @@ -12,7 +12,6 @@ function x_default_handler($xp,$data) $xp = xml_parser_create(); xml_set_default_handler($xp,'x_default_handler'); xml_parse($xp, '',TRUE); -xml_parser_free($xp); echo "Done\n"; ?> --EXPECT-- diff --git a/ext/xml/tests/bug30875.phpt b/ext/xml/tests/bug30875.phpt index eca12dd74ce31..70e26b8ff9b10 100644 --- a/ext/xml/tests/bug30875.phpt +++ b/ext/xml/tests/bug30875.phpt @@ -14,7 +14,6 @@ XML; $parser = xml_parser_create(); xml_parse_into_struct($parser, $xml, $vals); -xml_parser_free($parser); var_dump($vals); ?> --EXPECT-- diff --git a/ext/xml/tests/bug35447.phpt b/ext/xml/tests/bug35447.phpt index 229d59314d0bd..4161d14cd2902 100644 --- a/ext/xml/tests/bug35447.phpt +++ b/ext/xml/tests/bug35447.phpt @@ -24,7 +24,6 @@ END_OF_XML; $parser = xml_parser_create_ns('UTF-8'); xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); $result = xml_parse_into_struct($parser, $data, $vals, $index); -xml_parser_free($parser); var_dump($vals); ?> --EXPECT-- diff --git a/ext/xml/tests/bug46699.phpt b/ext/xml/tests/bug46699.phpt index b921ab39b7d31..d416c1f7f4bed 100644 --- a/ext/xml/tests/bug46699.phpt +++ b/ext/xml/tests/bug46699.phpt @@ -25,7 +25,6 @@ $parser = xml_parser_create_ns("ISO-8859-1","@"); xml_set_default_handler($parser,'defaultfunc'); xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); xml_parse($parser, $xml); -xml_parser_free($parser); ?> --EXPECTF--
diff --git a/ext/xml/tests/bug50576.phpt b/ext/xml/tests/bug50576.phpt index 3279966b3aad4..8370943a0f9f9 100644 --- a/ext/xml/tests/bug50576.phpt +++ b/ext/xml/tests/bug50576.phpt @@ -21,7 +21,6 @@ echo 'Index array' . PHP_EOL; print_r($index); echo 'Vals array' . PHP_EOL; print_r($vals); -xml_parser_free($xml_parser); function startElement($parser, $name, $attribs) { echo $name . PHP_EOL; } function endElement($parser, $name) { echo $name . PHP_EOL; } @@ -29,7 +28,6 @@ $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, 'startElement', 'endElement'); xml_parser_set_option($xml_parser, XML_OPTION_SKIP_TAGSTART, 4); xml_parse($xml_parser, $XML); -xml_parser_free($xml_parser); ?> --EXPECT-- diff --git a/ext/xml/tests/bug72714.phpt b/ext/xml/tests/bug72714.phpt index 4e964880ad139..9026dda6ba4c6 100644 --- a/ext/xml/tests/bug72714.phpt +++ b/ext/xml/tests/bug72714.phpt @@ -22,8 +22,6 @@ function parse($tagstart) { xml_parser_set_option($xml_parser, XML_OPTION_SKIP_TAGSTART, $tagstart); xml_parse($xml_parser, $xml); - - xml_parser_free($xml_parser); } parse(3015809298423721); diff --git a/ext/xml/tests/bug72793.phpt b/ext/xml/tests/bug72793.phpt index b9e53eaf3a54a..25bfee990d10b 100644 --- a/ext/xml/tests/bug72793.phpt +++ b/ext/xml/tests/bug72793.phpt @@ -33,4 +33,6 @@ $xml_parser->free(); ===DONE=== --EXPECTF-- Deprecated: Function xml_set_object() is deprecated since 8.4, provide a proper method callable to xml_set_*_handler() functions in %s on line %d + +Deprecated: Function xml_parser_free() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d ===DONE=== diff --git a/ext/xml/tests/bug76874.phpt b/ext/xml/tests/bug76874.phpt index 804fb24241e2d..1a1fe283d8e34 100644 --- a/ext/xml/tests/bug76874.phpt +++ b/ext/xml/tests/bug76874.phpt @@ -27,5 +27,6 @@ $object->test(); ?> ===DONE=== ---EXPECT-- +--EXPECTF-- +Deprecated: Function xml_parser_free() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d ===DONE=== diff --git a/ext/xml/tests/set_element_handler_trampoline.phpt b/ext/xml/tests/set_element_handler_trampoline.phpt index 884b6db219215..f5eada5c6caf9 100644 --- a/ext/xml/tests/set_element_handler_trampoline.phpt +++ b/ext/xml/tests/set_element_handler_trampoline.phpt @@ -42,21 +42,18 @@ echo "Both handlers are trampolines:\n"; $parser = xml_parser_create(); xml_set_element_handler($parser, $startCallback, $endCallback); xml_parse($parser, $xml, true); -xml_parser_free($parser); echo "\nStart handler is trampoline, end handler method string:\n"; $parser = xml_parser_create(); xml_set_object($parser, $customParser); xml_set_element_handler($parser, $startCallback, 'endHandler'); xml_parse($parser, $xml, true); -xml_parser_free($parser); echo "\nEnd handler is trampoline, start handler method string:\n"; $parser = xml_parser_create(); xml_set_object($parser, $customParser); xml_set_element_handler($parser, 'startHandler', $endCallback); xml_parse($parser, $xml, true); -xml_parser_free($parser); ?> --EXPECTF-- diff --git a/ext/xml/tests/set_element_handler_trampoline_errors.phpt b/ext/xml/tests/set_element_handler_trampoline_errors.phpt index 6d35ef5f4d9d2..52f8efb8ec9f4 100644 --- a/ext/xml/tests/set_element_handler_trampoline_errors.phpt +++ b/ext/xml/tests/set_element_handler_trampoline_errors.phpt @@ -36,7 +36,6 @@ try { } catch (\Throwable $e) { echo $e::class, ': ', $e->getMessage(), PHP_EOL; } -xml_parser_free($parser); ?> --EXPECT-- diff --git a/ext/xml/tests/set_handler_trampoline.phpt b/ext/xml/tests/set_handler_trampoline.phpt index 74c143c7aac11..552df7bf3eeef 100644 --- a/ext/xml/tests/set_handler_trampoline.phpt +++ b/ext/xml/tests/set_handler_trampoline.phpt @@ -24,7 +24,6 @@ HERE; $parser = xml_parser_create(); xml_set_processing_instruction_handler($parser, $callback); xml_parse($parser, $xml, true); -xml_parser_free($parser); ?> --EXPECT-- diff --git a/ext/xml/tests/xml001.phpt b/ext/xml/tests/xml001.phpt index 1bbe3c0fced04..1bc555efda4a8 100644 --- a/ext/xml/tests/xml001.phpt +++ b/ext/xml/tests/xml001.phpt @@ -30,7 +30,6 @@ while ($data = fread($fp, 4096)) { } } print "parse complete\n"; -xml_parser_free($xml_parser); function startElement($parser, $name, $attribs) { diff --git a/ext/xml/tests/xml002.phpt b/ext/xml/tests/xml002.phpt index b29c94f83d125..f8b84a75b8ec5 100644 --- a/ext/xml/tests/xml002.phpt +++ b/ext/xml/tests/xml002.phpt @@ -72,7 +72,6 @@ while ($data = fread($fp, 4096)) { } } print "parse complete\n"; -xml_parser_free($xml_parser); ?> --EXPECT-- diff --git a/ext/xml/tests/xml003.phpt b/ext/xml/tests/xml003.phpt index 2227133caa0c5..121a641443184 100644 --- a/ext/xml/tests/xml003.phpt +++ b/ext/xml/tests/xml003.phpt @@ -71,7 +71,6 @@ while ($data = fread($fp, 4096)) { } } print "parse complete\n"; -xml_parser_free($xml_parser); ?> --EXPECT-- {?[]}{?[ diff --git a/ext/xml/tests/xml004.phpt b/ext/xml/tests/xml004.phpt index 71c08c2f7356c..3479892f00720 100644 --- a/ext/xml/tests/xml004.phpt +++ b/ext/xml/tests/xml004.phpt @@ -13,7 +13,6 @@ $fp = fopen("xmltest.xml", "r"); while ($data = fread($fp, 4096)) { xml_parse($xp, $data, feof($fp)); } -xml_parser_free($xp); $xp = xml_parser_create(); xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xp, "start_element", "end_element"); @@ -21,7 +20,6 @@ $fp = fopen("xmltest.xml", "r"); while ($data = fread($fp, 4096)) { xml_parse($xp, $data, feof($fp)); } -xml_parser_free($xp); function start_element($xp, $elem, $attribs) { diff --git a/ext/xml/tests/xml009.phpt b/ext/xml/tests/xml009.phpt index 8986cebe607df..12f7e0269b106 100644 --- a/ext/xml/tests/xml009.phpt +++ b/ext/xml/tests/xml009.phpt @@ -28,7 +28,6 @@ $parser = xml_parser_create_ns("ISO-8859-1","@"); xml_set_element_handler($parser,'start_elem','end_elem'); xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); xml_parse($parser, $xml); -xml_parser_free($parser); ?> --EXPECT-- string(24) "http://example.com/foo@a" diff --git a/ext/xml/tests/xml010.phpt b/ext/xml/tests/xml010.phpt index 7a1f33785bc04..2ed5432efafb9 100644 --- a/ext/xml/tests/xml010.phpt +++ b/ext/xml/tests/xml010.phpt @@ -32,7 +32,6 @@ $parser = xml_parser_create_ns("ISO-8859-1","@"); xml_set_element_handler($parser,'start_elem','end_elem'); xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0); xml_parse($parser, $xml); -xml_parser_free($parser); ?> --EXPECT-- http://example.com/foo@a diff --git a/ext/xml/tests/xml011.phpt b/ext/xml/tests/xml011.phpt index f3557717e8f7e..d3e33fe326d93 100644 --- a/ext/xml/tests/xml011.phpt +++ b/ext/xml/tests/xml011.phpt @@ -17,7 +17,6 @@ $xml = 'start This & that'; $parser = xml_parser_create(); xml_parse_into_struct($parser, $xml, $vals, $index); print_r($vals); -xml_parser_free($parser); echo "\nChange to empty end handler\n"; $parser = xml_parser_create(); @@ -26,7 +25,6 @@ xml_set_element_handler($parser,'start_elem','end_elem'); xml_set_element_handler($parser,'start_elem',NULL); xml_parse($parser, $xml, TRUE); -xml_parser_free($parser); echo "\nDone\n"; ?> --EXPECT-- diff --git a/ext/xml/tests/xml_closures_001.phpt b/ext/xml/tests/xml_closures_001.phpt index a6c65a2676cdb..119e7b51a7db9 100644 --- a/ext/xml/tests/xml_closures_001.phpt +++ b/ext/xml/tests/xml_closures_001.phpt @@ -29,7 +29,6 @@ $fp = fopen("xmltest.xml", "r"); while ($data = fread($fp, 4096)) { xml_parse($xp, $data, feof($fp)); } -xml_parser_free($xp); ?> --EXPECT-- diff --git a/ext/xml/tests/xml_error_string_basic.inc b/ext/xml/tests/xml_error_string_basic.inc index e59bc411e57f9..ef9913d402d7c 100644 --- a/ext/xml/tests/xml_error_string_basic.inc +++ b/ext/xml/tests/xml_error_string_basic.inc @@ -13,5 +13,4 @@ foreach ($xmls as $xml) { var_dump(xml_get_error_code($xml_parser)); var_dump(xml_error_string(xml_get_error_code($xml_parser))); } - xml_parser_free($xml_parser); } \ No newline at end of file diff --git a/ext/xml/tests/xml_parse_into_struct_variation.phpt b/ext/xml/tests/xml_parse_into_struct_variation.phpt index 4571c4c73c521..a2067c937d063 100644 --- a/ext/xml/tests/xml_parse_into_struct_variation.phpt +++ b/ext/xml/tests/xml_parse_into_struct_variation.phpt @@ -9,7 +9,6 @@ echo "*** Testing xml_parse_into_struct() : variation ***\n"; $simple = "
simple notesimple note
"; $p = xml_parser_create(); xml_parse_into_struct($p, $simple, $vals, $index); -xml_parser_free($p); echo "Index array\n"; print_r($index); echo "\nVals array\n"; diff --git a/ext/xml/tests/xml_parser_free_deprecated.phpt b/ext/xml/tests/xml_parser_free_deprecated.phpt new file mode 100644 index 0000000000000..0bb2583ac927d --- /dev/null +++ b/ext/xml/tests/xml_parser_free_deprecated.phpt @@ -0,0 +1,15 @@ +--TEST-- +xml_parser_free() deprecation message +--EXTENSIONS-- +xml +--FILE-- +',TRUE); +xml_parser_free($xp); +echo "Done\n"; +?> +--EXPECTF-- +Deprecated: Function xml_parser_free() is deprecated since 8.5, as it has no effect since PHP 8.0 in %s on line %d +Done diff --git a/ext/xml/tests/xml_parser_set_option_basic.phpt b/ext/xml/tests/xml_parser_set_option_basic.phpt index 2256775c93b9c..e93d78437b341 100644 --- a/ext/xml/tests/xml_parser_set_option_basic.phpt +++ b/ext/xml/tests/xml_parser_set_option_basic.phpt @@ -26,8 +26,6 @@ var_dump(xml_parser_get_option($parser, XML_OPTION_TARGET_ENCODING)); var_dump(xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "US-ASCII")); var_dump(xml_parser_get_option($parser, XML_OPTION_TARGET_ENCODING)); -xml_parser_free( $parser ); - echo "Done\n"; ?> --EXPECT-- diff --git a/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt b/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt index ff2530cfead79..2f50847d5be5f 100644 --- a/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt +++ b/ext/xml/tests/xml_set_notation_decl_handler_basic.phpt @@ -32,7 +32,6 @@ class XML_Parser xml_set_notation_decl_handler($parser, $this->notation_decl_handler(...)); xml_set_unparsed_entity_decl_handler($parser, $this->unparsed_entity_decl_handler(...)); xml_parse($parser, $data, true); - xml_parser_free($parser); } } diff --git a/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt b/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt index 6041b2d44ee12..57bbaba20851a 100644 --- a/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt +++ b/ext/xml/tests/xml_set_processing_instruction_handler_basic.phpt @@ -18,7 +18,6 @@ class XML_Parser $parser = xml_parser_create(); xml_set_processing_instruction_handler($parser, $this->PIHandler(...)); xml_parse($parser, $data, true); - xml_parser_free($parser); } diff --git a/ext/xml/tests/xml_set_start_namespace_decl_handler_basic.inc b/ext/xml/tests/xml_set_start_namespace_decl_handler_basic.inc index b27b5c0efeb48..9da9a1f3b6aa4 100644 --- a/ext/xml/tests/xml_set_start_namespace_decl_handler_basic.inc +++ b/ext/xml/tests/xml_set_start_namespace_decl_handler_basic.inc @@ -14,7 +14,6 @@ var_dump(xml_set_start_namespace_decl_handler( $parser, "Namespace_Start_Handler var_dump(xml_set_end_namespace_decl_handler( $parser, "Namespace_End_Handler" )); xml_parse( $parser, $xml, true); -xml_parser_free( $parser ); echo "Done\n"; diff --git a/ext/xml/xml.stub.php b/ext/xml/xml.stub.php index 54c286ff845c8..f589c3b2c8f17 100644 --- a/ext/xml/xml.stub.php +++ b/ext/xml/xml.stub.php @@ -189,6 +189,7 @@ function xml_get_current_column_number(XMLParser $parser): int {} function xml_get_current_byte_index(XMLParser $parser): int {} +#[\Deprecated(since: '8.5', message: "as it has no effect since PHP 8.0")] function xml_parser_free(XMLParser $parser): bool {} /** @param string|int|bool $value */ diff --git a/ext/xml/xml_arginfo.h b/ext/xml/xml_arginfo.h index a432059a3f14e..784424e7fd3ae 100644 --- a/ext/xml/xml_arginfo.h +++ b/ext/xml/xml_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 94b232499672dfd61c2c585a5d1d8a27d1a4a7ce */ + * Stub hash: c7838fb209d601be280dfdebfd135906afa36e8c */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_xml_parser_create, 0, 0, XMLParser, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, encoding, IS_STRING, 1, "null") @@ -125,7 +125,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(xml_get_current_line_number, arginfo_xml_get_current_line_number) ZEND_FE(xml_get_current_column_number, arginfo_xml_get_current_column_number) ZEND_FE(xml_get_current_byte_index, arginfo_xml_get_current_byte_index) - ZEND_FE(xml_parser_free, arginfo_xml_parser_free) + ZEND_RAW_FENTRY("xml_parser_free", zif_xml_parser_free, arginfo_xml_parser_free, ZEND_ACC_DEPRECATED, NULL, NULL) ZEND_FE(xml_parser_set_option, arginfo_xml_parser_set_option) ZEND_FE(xml_parser_get_option, arginfo_xml_parser_get_option) ZEND_FE_END @@ -164,16 +164,18 @@ static void register_xml_symbols(int module_number) zend_attribute *attribute_Deprecated_func_xml_set_object_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "xml_set_object", sizeof("xml_set_object") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_xml_set_object_0_arg0; - zend_string *attribute_Deprecated_func_xml_set_object_0_arg0_str = zend_string_init("8.4", strlen("8.4"), 1); - ZVAL_STR(&attribute_Deprecated_func_xml_set_object_0_arg0, attribute_Deprecated_func_xml_set_object_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_xml_set_object_0->args[0].value, &attribute_Deprecated_func_xml_set_object_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_xml_set_object_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_4)); attribute_Deprecated_func_xml_set_object_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_xml_set_object_0_arg1; zend_string *attribute_Deprecated_func_xml_set_object_0_arg1_str = zend_string_init("provide a proper method callable to xml_set_*_handler() functions", strlen("provide a proper method callable to xml_set_*_handler() functions"), 1); - ZVAL_STR(&attribute_Deprecated_func_xml_set_object_0_arg1, attribute_Deprecated_func_xml_set_object_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_xml_set_object_0->args[1].value, &attribute_Deprecated_func_xml_set_object_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_xml_set_object_0->args[1].value, attribute_Deprecated_func_xml_set_object_0_arg1_str); attribute_Deprecated_func_xml_set_object_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_xml_parser_free_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "xml_parser_free", sizeof("xml_parser_free") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + ZVAL_STR(&attribute_Deprecated_func_xml_parser_free_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_5)); + attribute_Deprecated_func_xml_parser_free_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_xml_parser_free_0_arg1_str = zend_string_init("as it has no effect since PHP 8.0", strlen("as it has no effect since PHP 8.0"), 1); + ZVAL_STR(&attribute_Deprecated_func_xml_parser_free_0->args[1].value, attribute_Deprecated_func_xml_parser_free_0_arg1_str); + attribute_Deprecated_func_xml_parser_free_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } static zend_class_entry *register_class_XMLParser(void) diff --git a/ext/xmlreader/tests/gh19098.phpt b/ext/xmlreader/tests/gh19098.phpt new file mode 100644 index 0000000000000..13a6eda328f25 --- /dev/null +++ b/ext/xmlreader/tests/gh19098.phpt @@ -0,0 +1,44 @@ +--TEST-- +GH-19098 (libxml<2.13 segmentation fault caused by php_libxml_node_free) +--EXTENSIONS-- +xmlreader +dom +--FILE-- + + + + +'); + +$success = $xml_reader->next("sparql"); + +$success = $xml_reader->read(); +$success = $xml_reader->next("results"); + +while ($xml_reader->read()) { + if ($xml_reader->next("result")) { + $result_as_dom_node = $xml_reader->expand(); + $child = $result_as_dom_node->firstChild; + unset($result_as_dom_node); + var_dump($child->namespaceURI); + foreach ($child->attributes as $attr) { + var_dump($attr->namespaceURI); + } + $doc = new DOMDocument; + $doc->adoptNode($child); + echo $doc->saveXML($child), "\n"; + unset($child); + break; + } +} + +?> +--EXPECT-- +string(38) "http://www.w3.org/2005/sparql-results#" +string(36) "http://www.w3.org/XML/1998/namespace" +string(10) "urn:custom" +NULL + diff --git a/ext/xsl/php_xsl.stub.php b/ext/xsl/php_xsl.stub.php index 24da81b7d71b8..6fe39c1a606e3 100644 --- a/ext/xsl/php_xsl.stub.php +++ b/ext/xsl/php_xsl.stub.php @@ -2,11 +2,8 @@ /** @generate-class-entries */ -/** @var int */ const XSL_CLONE_AUTO = 0; -/** @var int */ const XSL_CLONE_NEVER = -1; -/** @var int */ const XSL_CLONE_ALWAYS = 1; /** diff --git a/ext/xsl/php_xsl_arginfo.h b/ext/xsl/php_xsl_arginfo.h index 72e7ed0b0a99d..d640d1114a566 100644 --- a/ext/xsl/php_xsl_arginfo.h +++ b/ext/xsl/php_xsl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 5b4ce3f5f7dee60bde803b3c2eb3994777f56914 */ + * Stub hash: cb1005b601e72e8d36d0f6aa5d08872f5c7ea2e6 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_XSLTProcessor_importStylesheet, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, stylesheet, IS_OBJECT, 0) diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index ea0f9232aced4..95e2e2e8754be 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -609,7 +609,7 @@ PHP_METHOD(XSLTProcessor, setParameter) RETURN_THROWS(); } - if (UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(string_key), ZSTR_LEN(string_key)))) { + if (UNEXPECTED(zend_str_has_nul_byte(string_key))) { zend_argument_value_error(3, "must not contain keys with any null bytes"); RETURN_THROWS(); } @@ -625,7 +625,7 @@ PHP_METHOD(XSLTProcessor, setParameter) RETURN_THROWS(); } - if (UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(str), ZSTR_LEN(str)))) { + if (UNEXPECTED(zend_str_has_nul_byte(str))) { zend_string_release(str); zend_string_release_ex(ht_key, false); zend_argument_value_error(3, "must not contain values with any null bytes"); @@ -643,7 +643,7 @@ PHP_METHOD(XSLTProcessor, setParameter) RETURN_THROWS(); } - if (UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(name), ZSTR_LEN(name)))) { + if (UNEXPECTED(zend_str_has_nul_byte(name))) { zend_argument_value_error(2, "must not contain any null bytes"); RETURN_THROWS(); } diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index 09391d8137aa6..7ec6f54312346 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -50,7 +50,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) int observer_fiber_switch; int observer_fiber_destroy; int observer_execute_internal; - HashTable global_weakmap; + HashTable *global_weakmap; int replace_zend_execute_ex; int register_passes; bool print_stderr_mshutdown; diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 14aad0d1a322e..99bdae0bcc7ac 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -14,6 +14,8 @@ +----------------------------------------------------------------------+ */ +#include "ext/opcache/zend_accelerator_api.h" +#include "zend_API.h" #include "zend_modules.h" #include "zend_types.h" #ifdef HAVE_CONFIG_H @@ -38,6 +40,7 @@ #include "zend_call_stack.h" #include "zend_exceptions.h" #include "zend_mm_custom_handlers.h" +#include "ext/uri/php_uri.h" #if defined(HAVE_LIBXML) && !defined(PHP_WIN32) # include @@ -85,6 +88,13 @@ static ZEND_FUNCTION(zend_test_func) EX(func) = NULL; } +static ZEND_FUNCTION(zend_trigger_bailout) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_error(E_ERROR, "Bailout"); +} + static ZEND_FUNCTION(zend_test_array_return) { ZEND_PARSE_PARAMETERS_NONE(); @@ -372,7 +382,7 @@ static ZEND_FUNCTION(zend_weakmap_attach) Z_PARAM_ZVAL(value) ZEND_PARSE_PARAMETERS_END(); - if (zend_weakrefs_hash_add(&ZT_G(global_weakmap), obj, value)) { + if (zend_weakrefs_hash_add(ZT_G(global_weakmap), obj, value)) { Z_TRY_ADDREF_P(value); RETURN_TRUE; } @@ -387,13 +397,13 @@ static ZEND_FUNCTION(zend_weakmap_remove) Z_PARAM_OBJ(obj) ZEND_PARSE_PARAMETERS_END(); - RETURN_BOOL(zend_weakrefs_hash_del(&ZT_G(global_weakmap), obj) == SUCCESS); + RETURN_BOOL(zend_weakrefs_hash_del(ZT_G(global_weakmap), obj) == SUCCESS); } static ZEND_FUNCTION(zend_weakmap_dump) { ZEND_PARSE_PARAMETERS_NONE(); - RETURN_ARR(zend_array_dup(&ZT_G(global_weakmap))); + RETURN_ARR(zend_array_dup(ZT_G(global_weakmap))); } static ZEND_FUNCTION(zend_get_current_func_name) @@ -514,6 +524,28 @@ static ZEND_FUNCTION(zend_object_init_with_constructor) ZVAL_COPY_VALUE(return_value, &obj); } +static ZEND_FUNCTION(zend_call_method_if_exists) +{ + zend_object *obj = NULL; + zend_string *method_name; + uint32_t num_args = 0; + zval *args = NULL; + ZEND_PARSE_PARAMETERS_START(2, -1) + Z_PARAM_OBJ(obj) + Z_PARAM_STR(method_name) + Z_PARAM_VARIADIC('*', args, num_args) + ZEND_PARSE_PARAMETERS_END(); + + zend_result status = zend_call_method_if_exists(obj, method_name, return_value, num_args, args); + if (status == FAILURE) { + ZEND_ASSERT(Z_ISUNDEF_P(return_value)); + if (EG(exception)) { + RETURN_THROWS(); + } + RETURN_NULL(); + } +} + static ZEND_FUNCTION(zend_get_unit_enum) { ZEND_PARSE_PARAMETERS_NONE(); @@ -693,6 +725,72 @@ static ZEND_FUNCTION(zend_test_crash) php_printf("%s", invalid); } +static ZEND_FUNCTION(zend_test_uri_parser) +{ + zend_string *uri_string; + zend_string *parser_name; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(uri_string) + Z_PARAM_STR(parser_name) + ZEND_PARSE_PARAMETERS_END(); + + const php_uri_parser *parser = php_uri_get_parser(parser_name); + if (parser == NULL) { + zend_argument_value_error(1, "Unknown parser"); + RETURN_THROWS(); + } + + uri_internal_t *uri = php_uri_parse(parser, ZSTR_VAL(uri_string), ZSTR_LEN(uri_string), false); + if (uri == NULL) { + RETURN_THROWS(); + } + + zval value; + + array_init(return_value); + zval normalized; + array_init(&normalized); + php_uri_get_scheme(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_SCHEME), &value); + php_uri_get_username(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_USERNAME), &value); + php_uri_get_password(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_PASSWORD), &value); + php_uri_get_host(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_HOST), &value); + php_uri_get_port(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_PORT), &value); + php_uri_get_path(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_PATH), &value); + php_uri_get_query(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_QUERY), &value); + php_uri_get_fragment(uri, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &value); + zend_hash_add(Z_ARR(normalized), ZSTR_KNOWN(ZEND_STR_FRAGMENT), &value); + zend_hash_str_add(Z_ARR_P(return_value), "normalized", strlen("normalized"), &normalized); + zval raw; + array_init(&raw); + php_uri_get_scheme(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_SCHEME), &value); + php_uri_get_username(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_USERNAME), &value); + php_uri_get_password(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_PASSWORD), &value); + php_uri_get_host(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_HOST), &value); + php_uri_get_port(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_PORT), &value); + php_uri_get_path(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_PATH), &value); + php_uri_get_query(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_QUERY), &value); + php_uri_get_fragment(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); + zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_FRAGMENT), &value); + zend_hash_str_add(Z_ARR_P(return_value), "raw", strlen("raw"), &raw); + + php_uri_free(uri); +} + static bool has_opline(zend_execute_data *execute_data) { return execute_data @@ -927,11 +1025,12 @@ static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, ze return zend_std_get_static_method(ce, name, NULL); } -void zend_attribute_validate_zendtestattribute(zend_attribute *attr, uint32_t target, zend_class_entry *scope) +zend_string *zend_attribute_validate_zendtestattribute(zend_attribute *attr, uint32_t target, zend_class_entry *scope) { if (target != ZEND_ATTRIBUTE_TARGET_CLASS) { - zend_error(E_COMPILE_ERROR, "Only classes can be marked with #[ZendTestAttribute]"); + return ZSTR_INIT_LITERAL("Only classes can be marked with #[ZendTestAttribute]", 0); } + return NULL; } static ZEND_METHOD(_ZendTestClass, __toString) @@ -1392,7 +1491,8 @@ PHP_MSHUTDOWN_FUNCTION(zend_test) PHP_RINIT_FUNCTION(zend_test) { - zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0); + ALLOC_HASHTABLE(ZT_G(global_weakmap)); + zend_hash_init(ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0); ZT_G(observer_nesting_depth) = 0; zend_test_mm_custom_handlers_rinit(); return SUCCESS; @@ -1400,7 +1500,8 @@ PHP_RINIT_FUNCTION(zend_test) PHP_RSHUTDOWN_FUNCTION(zend_test) { - zend_weakrefs_hash_destroy(&ZT_G(global_weakmap)); + zend_weakrefs_hash_destroy(ZT_G(global_weakmap)); + FREE_HASHTABLE(ZT_G(global_weakmap)); if (ZT_G(zend_test_heap)) { free(ZT_G(zend_test_heap)); @@ -1605,7 +1706,7 @@ static PHP_FUNCTION(zend_test_compile_to_ast) zend_arena *ast_arena; zend_ast *ast = zend_compile_string_to_ast(str, &ast_arena, ZSTR_EMPTY_ALLOC()); - + zend_string *result = zend_ast_export("", ast, ""); zend_ast_destroy(ast); @@ -1623,3 +1724,19 @@ static PHP_FUNCTION(zend_test_gh18756) zend_mm_gc(heap); zend_mm_shutdown(heap, true, false); } + +static PHP_FUNCTION(zend_test_opcache_preloading) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETURN_BOOL(opcache_preloading()); +} + +static PHP_FUNCTION(zend_test_gh19792) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETVAL_STRING("this is a non-interned string"); + zend_error(E_WARNING, "a warning"); + zend_throw_error(NULL, "an exception"); +} diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 528ec71ae7a3a..bf9a1c6b5bc8d 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -208,6 +208,8 @@ enum ZendTestIntEnum: int { case Baz = -1; } + function zend_trigger_bailout(): never {} + function zend_test_array_return(): array {} /** @genstubs-expose-comment-block @@ -293,6 +295,8 @@ function zend_call_method(object|string $obj_or_class, string $method, mixed $ar function zend_object_init_with_constructor(string $class, mixed ...$args): mixed {} + function zend_call_method_if_exists(object $obj, string $method, mixed ...$args): mixed {} + function zend_test_zend_ini_parse_quantity(string $str): int {} function zend_test_zend_ini_parse_uquantity(string $str): int {} @@ -336,6 +340,13 @@ function zend_test_log_err_debug(string $str): void {} function zend_test_compile_to_ast(string $str): string {} function zend_test_gh18756(): void {} + + function zend_test_opcache_preloading(): bool {} + + function zend_test_uri_parser(string $uri, string $parser): array { } + + /** @compile-time-eval */ + function zend_test_gh19792(): void {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 07b519f3d6a73..bd2240cedd637 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,8 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 13a5559e87cb073c921006bb3be5354b90247306 */ + * Stub hash: 6bccdc2444e6a68ba615fc281235a4551d0b8819 */ + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_trigger_bailout, 0, 0, IS_NEVER, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -113,6 +116,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_object_init_with_constructo ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_call_method_if_exists, 0, 2, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, obj, IS_OBJECT, 0) + ZEND_ARG_TYPE_INFO(0, method, IS_STRING, 0) + ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_zend_ini_parse_quantity, 0, 1, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -179,6 +188,15 @@ ZEND_END_ARG_INFO() #define arginfo_zend_test_gh18756 arginfo_zend_test_void_return +#define arginfo_zend_test_opcache_preloading arginfo_zend_test_is_pcre_bundled + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_uri_parser, 0, 2, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, parser, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_zend_test_gh19792 arginfo_zend_test_void_return + #define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled #define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return @@ -264,6 +282,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_ZendTestNS2_ZendSubNS_Foo_method arginfo_zend_test_void_return +static ZEND_FUNCTION(zend_trigger_bailout); static ZEND_FUNCTION(zend_test_array_return); static ZEND_FUNCTION(zend_test_nullable_array_return); static ZEND_FUNCTION(zend_test_void_return); @@ -293,6 +312,7 @@ static ZEND_FUNCTION(zend_test_attribute_with_named_argument); static ZEND_FUNCTION(zend_get_current_func_name); static ZEND_FUNCTION(zend_call_method); static ZEND_FUNCTION(zend_object_init_with_constructor); +static ZEND_FUNCTION(zend_call_method_if_exists); static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity); static ZEND_FUNCTION(zend_test_zend_ini_parse_uquantity); static ZEND_FUNCTION(zend_test_zend_ini_str); @@ -318,6 +338,9 @@ static ZEND_FUNCTION(zend_test_is_zend_ptr); static ZEND_FUNCTION(zend_test_log_err_debug); static ZEND_FUNCTION(zend_test_compile_to_ast); static ZEND_FUNCTION(zend_test_gh18756); +static ZEND_FUNCTION(zend_test_opcache_preloading); +static ZEND_FUNCTION(zend_test_uri_parser); +static ZEND_FUNCTION(zend_test_gh19792); static ZEND_FUNCTION(ZendTestNS2_namespaced_func); static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func); static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func); @@ -348,6 +371,7 @@ static ZEND_METHOD(ZendTestNS2_Foo, method); static ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo, method); static const zend_function_entry ext_functions[] = { + ZEND_FE(zend_trigger_bailout, arginfo_zend_trigger_bailout) ZEND_FE(zend_test_array_return, arginfo_zend_test_array_return) #if (PHP_VERSION_ID >= 80400) ZEND_RAW_FENTRY("zend_test_nullable_array_return", zif_zend_test_nullable_array_return, arginfo_zend_test_nullable_array_return, ZEND_ACC_COMPILE_TIME_EVAL, NULL, "/**\n * \"Lorem ipsum\"\n * @see https://www.php.net\n * @since 8.3\n */") @@ -419,6 +443,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_get_current_func_name, arginfo_zend_get_current_func_name) ZEND_FE(zend_call_method, arginfo_zend_call_method) ZEND_FE(zend_object_init_with_constructor, arginfo_zend_object_init_with_constructor) + ZEND_FE(zend_call_method_if_exists, arginfo_zend_call_method_if_exists) ZEND_FE(zend_test_zend_ini_parse_quantity, arginfo_zend_test_zend_ini_parse_quantity) ZEND_FE(zend_test_zend_ini_parse_uquantity, arginfo_zend_test_zend_ini_parse_uquantity) ZEND_FE(zend_test_zend_ini_str, arginfo_zend_test_zend_ini_str) @@ -444,6 +469,17 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_test_log_err_debug, arginfo_zend_test_log_err_debug) ZEND_FE(zend_test_compile_to_ast, arginfo_zend_test_compile_to_ast) ZEND_FE(zend_test_gh18756, arginfo_zend_test_gh18756) + ZEND_FE(zend_test_opcache_preloading, arginfo_zend_test_opcache_preloading) + ZEND_FE(zend_test_uri_parser, arginfo_zend_test_uri_parser) +#if (PHP_VERSION_ID >= 80400) + ZEND_RAW_FENTRY("zend_test_gh19792", zif_zend_test_gh19792, arginfo_zend_test_gh19792, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) +#else +#if (PHP_VERSION_ID >= 80200) + ZEND_RAW_FENTRY("zend_test_gh19792", zif_zend_test_gh19792, arginfo_zend_test_gh19792, ZEND_ACC_COMPILE_TIME_EVAL) +#elif (PHP_VERSION_ID >= 80000) + ZEND_RAW_FENTRY("zend_test_gh19792", zif_zend_test_gh19792, arginfo_zend_test_gh19792, 0) +#endif +#endif #if (PHP_VERSION_ID >= 80400) ZEND_RAW_FENTRY(ZEND_NS_NAME("ZendTestNS2", "namespaced_func"), zif_ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func, 0, NULL, NULL) #else @@ -591,69 +627,51 @@ static void register_test_symbols(int module_number) zend_string *attribute_name_Deprecated_func_zend_test_deprecated_attr_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, 1); zend_attribute *attribute_Deprecated_func_zend_test_deprecated_attr_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_deprecated_attr", sizeof("zend_test_deprecated_attr") - 1), attribute_name_Deprecated_func_zend_test_deprecated_attr_0, 1); zend_string_release(attribute_name_Deprecated_func_zend_test_deprecated_attr_0); - zval attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0; zend_string *attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0_str = zend_string_init("custom message", strlen("custom message"), 1); - ZVAL_STR(&attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0, attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zend_test_deprecated_attr_0->args[0].value, &attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zend_test_deprecated_attr_0->args[0].value, attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0_str); attribute_Deprecated_func_zend_test_deprecated_attr_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_zend_test_nodiscard_0 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_zend_test_nodiscard_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_nodiscard", sizeof("zend_test_nodiscard") - 1), attribute_name_NoDiscard_func_zend_test_nodiscard_0, 1); zend_string_release(attribute_name_NoDiscard_func_zend_test_nodiscard_0); - zval attribute_NoDiscard_func_zend_test_nodiscard_0_arg0; - zend_string *attribute_NoDiscard_func_zend_test_nodiscard_0_arg0_str = zend_string_init("custom message", strlen("custom message"), 1); - ZVAL_STR(&attribute_NoDiscard_func_zend_test_nodiscard_0_arg0, attribute_NoDiscard_func_zend_test_nodiscard_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_zend_test_nodiscard_0->args[0].value, &attribute_NoDiscard_func_zend_test_nodiscard_0_arg0); + ZVAL_STR_COPY(&attribute_NoDiscard_func_zend_test_nodiscard_0->args[0].value, attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0_str); attribute_NoDiscard_func_zend_test_nodiscard_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, 1); zend_attribute *attribute_Deprecated_func_zend_test_deprecated_nodiscard_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_deprecated_nodiscard", sizeof("zend_test_deprecated_nodiscard") - 1), attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0, 1); zend_string_release(attribute_name_Deprecated_func_zend_test_deprecated_nodiscard_0); - zval attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0; - zend_string *attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0_str = zend_string_init("custom message", strlen("custom message"), 1); - ZVAL_STR(&attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0, attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zend_test_deprecated_nodiscard_0->args[0].value, &attribute_Deprecated_func_zend_test_deprecated_nodiscard_0_arg0); + ZVAL_STR_COPY(&attribute_Deprecated_func_zend_test_deprecated_nodiscard_0->args[0].value, attribute_Deprecated_func_zend_test_deprecated_attr_0_arg0_str); attribute_Deprecated_func_zend_test_deprecated_nodiscard_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1 = zend_string_init_interned("NoDiscard", sizeof("NoDiscard") - 1, 1); zend_attribute *attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_deprecated_nodiscard", sizeof("zend_test_deprecated_nodiscard") - 1), attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1, 1); zend_string_release(attribute_name_NoDiscard_func_zend_test_deprecated_nodiscard_1); - zval attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0; zend_string *attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0_str = zend_string_init("custom message 2", strlen("custom message 2"), 1); - ZVAL_STR(&attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0, attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0_str); - ZVAL_COPY_VALUE(&attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1->args[0].value, &attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0); + ZVAL_STR(&attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1->args[0].value, attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1_arg0_str); attribute_NoDiscard_func_zend_test_deprecated_nodiscard_1->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_string *attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); zend_attribute *attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_parameter_with_attribute", sizeof("zend_test_parameter_with_attribute") - 1), 0, attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0, 1); zend_string_release(attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0); - zval attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0; zend_string *attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str = zend_string_init("value1", strlen("value1"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0->args[0].value, attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str); zend_string *attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0 = zend_string_init_interned("ZendTestAttributeWithArguments", sizeof("ZendTestAttributeWithArguments") - 1, 1); zend_attribute *attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_attribute_with_named_argument", sizeof("zend_test_attribute_with_named_argument") - 1), attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0, 1); zend_string_release(attribute_name_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0); - zval attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0; zend_string *attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0_str = zend_string_init("foo", strlen("foo"), 1); - ZVAL_STR(&attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0, attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].value, &attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0); + ZVAL_STR(&attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].value, attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0_arg0_str); attribute_ZendTestAttributeWithArguments_func_zend_test_attribute_with_named_argument_0->args[0].name = zend_string_init_interned("arg", sizeof("arg") - 1, 1); #if (PHP_VERSION_ID >= 80500) zend_constant *const_ZEND_TEST_ATTRIBUTED_CONSTANT = zend_hash_str_find_ptr(EG(zend_constants), "ZEND_TEST_ATTRIBUTED_CONSTANT", sizeof("ZEND_TEST_ATTRIBUTED_CONSTANT") - 1); zend_attribute *attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0 = zend_add_global_constant_attribute(const_ZEND_TEST_ATTRIBUTED_CONSTANT, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg0; zend_string *attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg0_str = zend_string_init("use something else", strlen("use something else"), 1); - ZVAL_STR(&attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg0, attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0->args[0].value, &attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg0); + ZVAL_STR(&attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0->args[0].value, attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg0_str); attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); - zval attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg1; zend_string *attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg1_str = zend_string_init("version 1.5", strlen("version 1.5"), 1); - ZVAL_STR(&attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg1, attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0->args[1].value, &attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg1); + ZVAL_STR(&attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0->args[1].value, attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0_arg1_str); attribute_Deprecated_const_ZEND_TEST_ATTRIBUTED_CONSTANT_0->args[1].name = ZSTR_KNOWN(ZEND_STR_SINCE); #endif } @@ -813,10 +831,8 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e zend_string *attribute_name_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0 = zend_string_init_interned("Deprecated", sizeof("Deprecated") - 1, 1); zend_attribute *attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0 = zend_add_class_constant_attribute(class_entry, const_ZEND_TEST_DEPRECATED_ATTR, attribute_name_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0, 1); zend_string_release(attribute_name_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0); - zval attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0_arg0; zend_string *attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0_arg0_str = zend_string_init("custom message", strlen("custom message"), 1); - ZVAL_STR(&attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0_arg0, attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0->args[0].value, &attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0_arg0); + ZVAL_STR(&attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0->args[0].value, attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0_arg0_str); attribute_Deprecated_const_ZEND_TEST_DEPRECATED_ATTR_0->args[0].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); return class_entry; @@ -923,10 +939,8 @@ static zend_class_entry *register_class_ZendAttributeTest(void) zend_string *attribute_name_ZendTestPropertyAttribute_property_testProp_1 = zend_string_init_interned("ZendTestPropertyAttribute", sizeof("ZendTestPropertyAttribute") - 1, 1); zend_attribute *attribute_ZendTestPropertyAttribute_property_testProp_1 = zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestPropertyAttribute_property_testProp_1, 1); zend_string_release(attribute_name_ZendTestPropertyAttribute_property_testProp_1); - zval attribute_ZendTestPropertyAttribute_property_testProp_1_arg0; zend_string *attribute_ZendTestPropertyAttribute_property_testProp_1_arg0_str = zend_string_init("testProp", strlen("testProp"), 1); - ZVAL_STR(&attribute_ZendTestPropertyAttribute_property_testProp_1_arg0, attribute_ZendTestPropertyAttribute_property_testProp_1_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestPropertyAttribute_property_testProp_1->args[0].value, &attribute_ZendTestPropertyAttribute_property_testProp_1_arg0); + ZVAL_STR(&attribute_ZendTestPropertyAttribute_property_testProp_1->args[0].value, attribute_ZendTestPropertyAttribute_property_testProp_1_arg0_str); zend_string *attribute_name_ZendTestAttribute_func_testmethod_0 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); @@ -985,9 +999,7 @@ static zend_class_entry *register_class_ZendTestAttribute(void) zend_string *attribute_name_Attribute_class_ZendTestAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_ZendTestAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttribute_0, 1); zend_string_release(attribute_name_Attribute_class_ZendTestAttribute_0); - zval attribute_Attribute_class_ZendTestAttribute_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_ALL); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestAttribute_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_ALL); return class_entry; } @@ -1017,9 +1029,7 @@ static zend_class_entry *register_class_ZendTestAttributeWithArguments(void) zend_string *attribute_name_Attribute_class_ZendTestAttributeWithArguments_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_ZendTestAttributeWithArguments_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttributeWithArguments_0, 1); zend_string_release(attribute_name_Attribute_class_ZendTestAttributeWithArguments_0); - zval attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0, ZEND_ATTRIBUTE_TARGET_ALL); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttributeWithArguments_0->args[0].value, &attribute_Attribute_class_ZendTestAttributeWithArguments_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_ZendTestAttributeWithArguments_0->args[0].value, ZEND_ATTRIBUTE_TARGET_ALL); return class_entry; } @@ -1039,9 +1049,7 @@ static zend_class_entry *register_class_ZendTestRepeatableAttribute(void) zend_string *attribute_name_Attribute_class_ZendTestRepeatableAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_ZendTestRepeatableAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestRepeatableAttribute_0, 1); zend_string_release(attribute_name_Attribute_class_ZendTestRepeatableAttribute_0); - zval attribute_Attribute_class_ZendTestRepeatableAttribute_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestRepeatableAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_ALL | ZEND_ATTRIBUTE_IS_REPEATABLE); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestRepeatableAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestRepeatableAttribute_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_ZendTestRepeatableAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_ALL | ZEND_ATTRIBUTE_IS_REPEATABLE); return class_entry; } @@ -1067,9 +1075,7 @@ static zend_class_entry *register_class_ZendTestParameterAttribute(void) zend_string *attribute_name_Attribute_class_ZendTestParameterAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_ZendTestParameterAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestParameterAttribute_0, 1); zend_string_release(attribute_name_Attribute_class_ZendTestParameterAttribute_0); - zval attribute_Attribute_class_ZendTestParameterAttribute_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestParameterAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestParameterAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestParameterAttribute_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_ZendTestParameterAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_PARAMETER); return class_entry; } @@ -1099,9 +1105,7 @@ static zend_class_entry *register_class_ZendTestPropertyAttribute(void) zend_string *attribute_name_Attribute_class_ZendTestPropertyAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); zend_attribute *attribute_Attribute_class_ZendTestPropertyAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestPropertyAttribute_0, 1); zend_string_release(attribute_name_Attribute_class_ZendTestPropertyAttribute_0); - zval attribute_Attribute_class_ZendTestPropertyAttribute_0_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestPropertyAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_PROPERTY); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestPropertyAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestPropertyAttribute_0_arg0); + ZVAL_LONG(&attribute_Attribute_class_ZendTestPropertyAttribute_0->args[0].value, ZEND_ATTRIBUTE_TARGET_PROPERTY); return class_entry; } @@ -1121,18 +1125,14 @@ static zend_class_entry *register_class_ZendTestClassWithMethodWithParameterAttr zend_string *attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); zend_attribute *attribute_ZendTestParameterAttribute_func_no_override_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "no_override", sizeof("no_override") - 1), 0, attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0, 1); zend_string_release(attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0); - zval attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0; zend_string *attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0_str = zend_string_init("value2", strlen("value2"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_no_override_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_no_override_arg0_0->args[0].value, attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0_str); zend_string *attribute_name_ZendTestParameterAttribute_func_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); zend_attribute *attribute_ZendTestParameterAttribute_func_override_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "override", sizeof("override") - 1), 0, attribute_name_ZendTestParameterAttribute_func_override_arg0_0, 1); zend_string_release(attribute_name_ZendTestParameterAttribute_func_override_arg0_0); - zval attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0; zend_string *attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str = zend_string_init("value3", strlen("value3"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_override_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_override_arg0_0->args[0].value, attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str); return class_entry; } @@ -1152,10 +1152,8 @@ static zend_class_entry *register_class_ZendTestChildClassWithMethodWithParamete zend_string *attribute_name_ZendTestParameterAttribute_func_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); zend_attribute *attribute_ZendTestParameterAttribute_func_override_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "override", sizeof("override") - 1), 0, attribute_name_ZendTestParameterAttribute_func_override_arg0_0, 1); zend_string_release(attribute_name_ZendTestParameterAttribute_func_override_arg0_0); - zval attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0; zend_string *attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str = zend_string_init("value4", strlen("value4"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_override_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_override_arg0_0->args[0].value, attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str); return class_entry; } diff --git a/ext/zend_test/tests/gh19720.phpt b/ext/zend_test/tests/gh19720.phpt new file mode 100644 index 0000000000000..627444c4793a8 --- /dev/null +++ b/ext/zend_test/tests/gh19720.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-19720 (Assertion failure when error handler throws when accessing a deprecated constant) +--EXTENSIONS-- +zend_test +--FILE-- + 42]; +} + +set_error_handler(function ($_, $errstr) { + throw new Exception($errstr); +}); + +try { + var_dump(Test::MyConst); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Constant ZEND_TEST_DEPRECATED is deprecated diff --git a/ext/zend_test/tests/gh9871.phpt b/ext/zend_test/tests/gh9871.phpt index b40a20a2609ec..d1a1be1a520bc 100644 --- a/ext/zend_test/tests/gh9871.phpt +++ b/ext/zend_test/tests/gh9871.phpt @@ -19,7 +19,7 @@ class A { } $property = new MyReflectionProperty('A', 'protected'); -$property->setAccessible(true); +$property->isStatic(); ?> --EXPECTF-- @@ -28,7 +28,7 @@ $property->setAccessible(true); - - - + + + diff --git a/ext/zend_test/tests/observer_sqlite_create_function.phpt b/ext/zend_test/tests/observer_sqlite_create_function.phpt index ac9b204de3a98..5d809056193d0 100644 --- a/ext/zend_test/tests/observer_sqlite_create_function.phpt +++ b/ext/zend_test/tests/observer_sqlite_create_function.phpt @@ -30,6 +30,11 @@ echo 'Done' . PHP_EOL; + + + + +Deprecated: Method PDO::sqliteCreateFunction() is deprecated since 8.5, use Pdo\Sqlite::createFunction() instead in %s on line %d diff --git a/ext/zend_test/tests/zend_call_method_if_exists/existing-non-public-methods.phpt b/ext/zend_test/tests/zend_call_method_if_exists/existing-non-public-methods.phpt new file mode 100644 index 0000000000000..cb65aadcfbbae --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/existing-non-public-methods.phpt @@ -0,0 +1,27 @@ +--TEST-- +zend_call_method_if_exists() with existing non public methods +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +NULL +NULL diff --git a/ext/zend_test/tests/zend_call_method_if_exists/existing-private-methods-within-scope.phpt b/ext/zend_test/tests/zend_call_method_if_exists/existing-private-methods-within-scope.phpt new file mode 100644 index 0000000000000..a1677b353b28f --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/existing-private-methods-within-scope.phpt @@ -0,0 +1,23 @@ +--TEST-- +zend_call_method_if_exists() with existing public method +--EXTENSIONS-- +zend_test +--FILE-- +priv() + zend_call_method_if_exists($this, 'priv'); + } +} + +$c = new C(); +$c->test(); + +?> +--EXPECT-- +string(7) "C::priv" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/existing-public-methods.phpt b/ext/zend_test/tests/zend_call_method_if_exists/existing-public-methods.phpt new file mode 100644 index 0000000000000..c9bbd8cd13b21 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/existing-public-methods.phpt @@ -0,0 +1,21 @@ +--TEST-- +zend_call_method_if_exists() with existing public method +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(6) "A::foo" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/existing-static-non-public-methods.phpt b/ext/zend_test/tests/zend_call_method_if_exists/existing-static-non-public-methods.phpt new file mode 100644 index 0000000000000..a08124a442066 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/existing-static-non-public-methods.phpt @@ -0,0 +1,27 @@ +--TEST-- +zend_call_method_if_exists() with existing non public static methods +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +NULL +NULL diff --git a/ext/zend_test/tests/zend_call_method_if_exists/existing-static-public-methods.phpt b/ext/zend_test/tests/zend_call_method_if_exists/existing-static-public-methods.phpt new file mode 100644 index 0000000000000..cc879a5b1aa3f --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/existing-static-public-methods.phpt @@ -0,0 +1,21 @@ +--TEST-- +zend_call_method_if_exists() with existing static public method +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(6) "A::foo" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/extended-non-existing-method-with-trampoline.phpt b/ext/zend_test/tests/zend_call_method_if_exists/extended-non-existing-method-with-trampoline.phpt new file mode 100644 index 0000000000000..fea9bc7902821 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/extended-non-existing-method-with-trampoline.phpt @@ -0,0 +1,27 @@ +--TEST-- +zend_call_method_if_exists() with non existing method on extended class with a trampoline +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(24) "In B trampoline for bar!" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/extended-non-existing-method-with-trampoline2.phpt b/ext/zend_test/tests/zend_call_method_if_exists/extended-non-existing-method-with-trampoline2.phpt new file mode 100644 index 0000000000000..41092d2252189 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/extended-non-existing-method-with-trampoline2.phpt @@ -0,0 +1,23 @@ +--TEST-- +zend_call_method_if_exists() with non existing method on extended class with a trampoline +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(24) "In A trampoline for bar!" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/method-throws-exception.phpt b/ext/zend_test/tests/zend_call_method_if_exists/method-throws-exception.phpt new file mode 100644 index 0000000000000..f70e160042bb4 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/method-throws-exception.phpt @@ -0,0 +1,25 @@ +--TEST-- +zend_call_method_if_exists() with throwing method +--EXTENSIONS-- +zend_test +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Exception: Error diff --git a/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-both-trampoline.phpt b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-both-trampoline.phpt new file mode 100644 index 0000000000000..d2f3d0fa30a8d --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-both-trampoline.phpt @@ -0,0 +1,44 @@ +--TEST-- +zend_call_method_if_exists() with non existing method on class with a trampoline and static trampoline +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(24) "In A trampoline for bar!" +string(24) "In B trampoline for bar!" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-static-trampoline.phpt b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-static-trampoline.phpt new file mode 100644 index 0000000000000..3b111b14ea298 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-static-trampoline.phpt @@ -0,0 +1,24 @@ +--TEST-- +zend_call_method_if_exists() with non existing method on class with a static trampoline +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +NULL diff --git a/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-trampoline.phpt b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-trampoline.phpt new file mode 100644 index 0000000000000..335c1a2d00c88 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-method-with-trampoline.phpt @@ -0,0 +1,24 @@ +--TEST-- +zend_call_method_if_exists() with non existing method on class with a trampoline +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(22) "In trampoline for bar!" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/non-existing-methods.phpt b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-methods.phpt new file mode 100644 index 0000000000000..2c570b35c81f1 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/non-existing-methods.phpt @@ -0,0 +1,21 @@ +--TEST-- +zend_call_method_if_exists() with non existing method +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +NULL diff --git a/ext/zend_test/tests/zend_call_method_if_exists/shadowing-private-method-with-trampoline.phpt b/ext/zend_test/tests/zend_call_method_if_exists/shadowing-private-method-with-trampoline.phpt new file mode 100644 index 0000000000000..459947c996ef3 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/shadowing-private-method-with-trampoline.phpt @@ -0,0 +1,24 @@ +--TEST-- +zend_call_method_if_exists() shadowing a private method +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(22) "In trampoline for foo!" diff --git a/ext/zend_test/tests/zend_call_method_if_exists/shadowing-private-method.phpt b/ext/zend_test/tests/zend_call_method_if_exists/shadowing-private-method.phpt new file mode 100644 index 0000000000000..5f4e0ce222e80 --- /dev/null +++ b/ext/zend_test/tests/zend_call_method_if_exists/shadowing-private-method.phpt @@ -0,0 +1,27 @@ +--TEST-- +zend_call_method_if_exists() shadowing a private method +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECT-- +string(6) "B::foo" diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 450c297762b87..4fcb66f8faf31 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -211,6 +211,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s return 0; } else if (len > MAXPATHLEN) { php_error_docref(NULL, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN); + efree(fullpath); efree(file_dirname_fullpath); zend_string_release_ex(file_basename, 0); CWD_STATE_FREE(new_state.cwd); @@ -627,7 +628,6 @@ int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_v can be used for simple glob() calls without further error checking. */ - array_init(return_value); return 0; } #endif @@ -636,7 +636,6 @@ int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_v /* now catch the FreeBSD style of "no matches" */ if (!globbuf.gl_pathc || !globbuf.gl_pathv) { - array_init(return_value); return 0; } @@ -1743,7 +1742,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0); file_stripped = ZSTR_VAL(basename); file_stripped_len = ZSTR_LEN(basename); - } else if (opts.remove_path && !memcmp(Z_STRVAL_P(zval_file), opts.remove_path, opts.remove_path_len)) { + } else if (opts.remove_path && Z_STRLEN_P(zval_file) > opts.remove_path_len && !memcmp(Z_STRVAL_P(zval_file), opts.remove_path, opts.remove_path_len)) { if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) { file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1; file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1; diff --git a/ext/zip/php_zip_arginfo.h b/ext/zip/php_zip_arginfo.h index c8dab41560e48..2a24750142c95 100644 --- a/ext/zip/php_zip_arginfo.h +++ b/ext/zip/php_zip_arginfo.h @@ -465,113 +465,63 @@ static void register_php_zip_symbols(int module_number) { zend_attribute *attribute_Deprecated_func_zip_open_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_open", sizeof("zip_open") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_open_0_arg0; - zend_string *attribute_Deprecated_func_zip_open_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_open_0_arg0, attribute_Deprecated_func_zip_open_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_open_0->args[0].value, &attribute_Deprecated_func_zip_open_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_open_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_open_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_open_0_arg1; zend_string *attribute_Deprecated_func_zip_open_0_arg1_str = zend_string_init("use ZipArchive::open() instead", strlen("use ZipArchive::open() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_open_0_arg1, attribute_Deprecated_func_zip_open_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_open_0->args[1].value, &attribute_Deprecated_func_zip_open_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_zip_open_0->args[1].value, attribute_Deprecated_func_zip_open_0_arg1_str); attribute_Deprecated_func_zip_open_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_zip_close_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_close", sizeof("zip_close") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_close_0_arg0; - zend_string *attribute_Deprecated_func_zip_close_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_close_0_arg0, attribute_Deprecated_func_zip_close_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_close_0->args[0].value, &attribute_Deprecated_func_zip_close_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_close_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_close_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_close_0_arg1; zend_string *attribute_Deprecated_func_zip_close_0_arg1_str = zend_string_init("use ZipArchive::close() instead", strlen("use ZipArchive::close() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_close_0_arg1, attribute_Deprecated_func_zip_close_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_close_0->args[1].value, &attribute_Deprecated_func_zip_close_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_zip_close_0->args[1].value, attribute_Deprecated_func_zip_close_0_arg1_str); attribute_Deprecated_func_zip_close_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_zip_read_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_read", sizeof("zip_read") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_read_0_arg0; - zend_string *attribute_Deprecated_func_zip_read_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_read_0_arg0, attribute_Deprecated_func_zip_read_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_read_0->args[0].value, &attribute_Deprecated_func_zip_read_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_read_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_read_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_read_0_arg1; zend_string *attribute_Deprecated_func_zip_read_0_arg1_str = zend_string_init("use ZipArchive::statIndex() instead", strlen("use ZipArchive::statIndex() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_read_0_arg1, attribute_Deprecated_func_zip_read_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_read_0->args[1].value, &attribute_Deprecated_func_zip_read_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_zip_read_0->args[1].value, attribute_Deprecated_func_zip_read_0_arg1_str); attribute_Deprecated_func_zip_read_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_zip_entry_open_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_entry_open", sizeof("zip_entry_open") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_zip_entry_open_0_arg0; - zend_string *attribute_Deprecated_func_zip_entry_open_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_open_0_arg0, attribute_Deprecated_func_zip_entry_open_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_open_0->args[0].value, &attribute_Deprecated_func_zip_entry_open_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_open_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_entry_open_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_zip_entry_close_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_entry_close", sizeof("zip_entry_close") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_func_zip_entry_close_0_arg0; - zend_string *attribute_Deprecated_func_zip_entry_close_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_close_0_arg0, attribute_Deprecated_func_zip_entry_close_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_close_0->args[0].value, &attribute_Deprecated_func_zip_entry_close_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_close_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_entry_close_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); zend_attribute *attribute_Deprecated_func_zip_entry_read_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_entry_read", sizeof("zip_entry_read") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_entry_read_0_arg0; - zend_string *attribute_Deprecated_func_zip_entry_read_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_read_0_arg0, attribute_Deprecated_func_zip_entry_read_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_read_0->args[0].value, &attribute_Deprecated_func_zip_entry_read_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_read_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_entry_read_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_entry_read_0_arg1; zend_string *attribute_Deprecated_func_zip_entry_read_0_arg1_str = zend_string_init("use ZipArchive::getFromIndex() instead", strlen("use ZipArchive::getFromIndex() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_read_0_arg1, attribute_Deprecated_func_zip_entry_read_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_read_0->args[1].value, &attribute_Deprecated_func_zip_entry_read_0_arg1); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_read_0->args[1].value, attribute_Deprecated_func_zip_entry_read_0_arg1_str); attribute_Deprecated_func_zip_entry_read_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_zip_entry_name_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_entry_name", sizeof("zip_entry_name") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_entry_name_0_arg0; - zend_string *attribute_Deprecated_func_zip_entry_name_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_name_0_arg0, attribute_Deprecated_func_zip_entry_name_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_name_0->args[0].value, &attribute_Deprecated_func_zip_entry_name_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_name_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_entry_name_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_entry_name_0_arg1; - zend_string *attribute_Deprecated_func_zip_entry_name_0_arg1_str = zend_string_init("use ZipArchive::statIndex() instead", strlen("use ZipArchive::statIndex() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_name_0_arg1, attribute_Deprecated_func_zip_entry_name_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_name_0->args[1].value, &attribute_Deprecated_func_zip_entry_name_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_zip_entry_name_0->args[1].value, attribute_Deprecated_func_zip_read_0_arg1_str); attribute_Deprecated_func_zip_entry_name_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_zip_entry_compressedsize_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_entry_compressedsize", sizeof("zip_entry_compressedsize") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_entry_compressedsize_0_arg0; - zend_string *attribute_Deprecated_func_zip_entry_compressedsize_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_compressedsize_0_arg0, attribute_Deprecated_func_zip_entry_compressedsize_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_compressedsize_0->args[0].value, &attribute_Deprecated_func_zip_entry_compressedsize_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_compressedsize_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_entry_compressedsize_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_entry_compressedsize_0_arg1; - zend_string *attribute_Deprecated_func_zip_entry_compressedsize_0_arg1_str = zend_string_init("use ZipArchive::statIndex() instead", strlen("use ZipArchive::statIndex() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_compressedsize_0_arg1, attribute_Deprecated_func_zip_entry_compressedsize_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_compressedsize_0->args[1].value, &attribute_Deprecated_func_zip_entry_compressedsize_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_zip_entry_compressedsize_0->args[1].value, attribute_Deprecated_func_zip_read_0_arg1_str); attribute_Deprecated_func_zip_entry_compressedsize_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_zip_entry_filesize_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_entry_filesize", sizeof("zip_entry_filesize") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_entry_filesize_0_arg0; - zend_string *attribute_Deprecated_func_zip_entry_filesize_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_filesize_0_arg0, attribute_Deprecated_func_zip_entry_filesize_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_filesize_0->args[0].value, &attribute_Deprecated_func_zip_entry_filesize_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_filesize_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_entry_filesize_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_entry_filesize_0_arg1; - zend_string *attribute_Deprecated_func_zip_entry_filesize_0_arg1_str = zend_string_init("use ZipArchive::statIndex() instead", strlen("use ZipArchive::statIndex() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_filesize_0_arg1, attribute_Deprecated_func_zip_entry_filesize_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_filesize_0->args[1].value, &attribute_Deprecated_func_zip_entry_filesize_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_zip_entry_filesize_0->args[1].value, attribute_Deprecated_func_zip_read_0_arg1_str); attribute_Deprecated_func_zip_entry_filesize_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); zend_attribute *attribute_Deprecated_func_zip_entry_compressionmethod_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "zip_entry_compressionmethod", sizeof("zip_entry_compressionmethod") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); - zval attribute_Deprecated_func_zip_entry_compressionmethod_0_arg0; - zend_string *attribute_Deprecated_func_zip_entry_compressionmethod_0_arg0_str = zend_string_init("8.0", strlen("8.0"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_compressionmethod_0_arg0, attribute_Deprecated_func_zip_entry_compressionmethod_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_compressionmethod_0->args[0].value, &attribute_Deprecated_func_zip_entry_compressionmethod_0_arg0); + ZVAL_STR(&attribute_Deprecated_func_zip_entry_compressionmethod_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_0)); attribute_Deprecated_func_zip_entry_compressionmethod_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); - zval attribute_Deprecated_func_zip_entry_compressionmethod_0_arg1; - zend_string *attribute_Deprecated_func_zip_entry_compressionmethod_0_arg1_str = zend_string_init("use ZipArchive::statIndex() instead", strlen("use ZipArchive::statIndex() instead"), 1); - ZVAL_STR(&attribute_Deprecated_func_zip_entry_compressionmethod_0_arg1, attribute_Deprecated_func_zip_entry_compressionmethod_0_arg1_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_func_zip_entry_compressionmethod_0->args[1].value, &attribute_Deprecated_func_zip_entry_compressionmethod_0_arg1); + ZVAL_STR_COPY(&attribute_Deprecated_func_zip_entry_compressionmethod_0->args[1].value, attribute_Deprecated_func_zip_read_0_arg1_str); attribute_Deprecated_func_zip_entry_compressionmethod_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); } @@ -1323,10 +1273,7 @@ static zend_class_entry *register_class_ZipArchive(zend_class_entry *class_entry #if defined(ZIP_FL_RECOMPRESS) zend_attribute *attribute_Deprecated_const_FL_RECOMPRESS_0 = zend_add_class_constant_attribute(class_entry, const_FL_RECOMPRESS, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 1); - zval attribute_Deprecated_const_FL_RECOMPRESS_0_arg0; - zend_string *attribute_Deprecated_const_FL_RECOMPRESS_0_arg0_str = zend_string_init("8.3", strlen("8.3"), 1); - ZVAL_STR(&attribute_Deprecated_const_FL_RECOMPRESS_0_arg0, attribute_Deprecated_const_FL_RECOMPRESS_0_arg0_str); - ZVAL_COPY_VALUE(&attribute_Deprecated_const_FL_RECOMPRESS_0->args[0].value, &attribute_Deprecated_const_FL_RECOMPRESS_0_arg0); + ZVAL_STR(&attribute_Deprecated_const_FL_RECOMPRESS_0->args[0].value, ZSTR_KNOWN(ZEND_STR_8_DOT_3)); attribute_Deprecated_const_FL_RECOMPRESS_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); #endif diff --git a/ext/zip/tests/bug53603.phpt b/ext/zip/tests/bug53603.phpt index 5423206233977..914b0b8440c61 100644 --- a/ext/zip/tests/bug53603.phpt +++ b/ext/zip/tests/bug53603.phpt @@ -28,5 +28,5 @@ $a = $zip->extractTo('teststream://test'); var_dump($a); ?> --EXPECTF-- -Warning: ZipArchive::extractTo(teststream://test/foo): Failed to open stream: "TestStream::stream_open" call failed in %s on line %d +Warning: ZipArchive::extractTo(teststream://test/foo): Failed to open stream: "TestStream::stream_open" is not implemented in %s on line %d bool(false) diff --git a/ext/zip/tests/gh19688.phpt b/ext/zip/tests/gh19688.phpt new file mode 100644 index 0000000000000..7e2a2800b2553 --- /dev/null +++ b/ext/zip/tests/gh19688.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-19688 (Remove pattern overflow in zip addGlob()) +--EXTENSIONS-- +zip +--FILE-- +open($filename, ZipArchive::CREATE | ZipArchive::OVERWRITE); +$options = array('remove_path' => $dir . 'a very long string here that will overrun'); +$zip->addGlob($testfile, 0, $options); +var_dump($zip->getNameIndex(0)); +?> +--CLEAN-- + +--EXPECTF-- +string(%d) "%s001.phpt" diff --git a/main/SAPI.c b/main/SAPI.c index 866b44c3eac7d..169ae572fa967 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -597,7 +597,8 @@ static void sapi_update_response_code(int ncode) * since zend_llist_del_element only removes one matched item once, * we should remove them manually */ -static void sapi_remove_header(zend_llist *l, char *name, size_t len) { +static void sapi_remove_header(zend_llist *l, char *name, size_t len, size_t header_len) +{ sapi_header_struct *header; zend_llist_element *next; zend_llist_element *current=l->head; @@ -605,7 +606,8 @@ static void sapi_remove_header(zend_llist *l, char *name, size_t len) { while (current) { header = (sapi_header_struct *)(current->data); next = current->next; - if (header->header_len > len && header->header[len] == ':' + if (header->header_len > header_len + && (header->header[header_len] == ':' || len > header_len) && !strncasecmp(header->header, name, len)) { if (current->prev) { current->prev->next = next; @@ -653,7 +655,7 @@ static void sapi_header_add_op(sapi_header_op_enum op, sapi_header_struct *sapi_ char sav = *colon_offset; *colon_offset = 0; - sapi_remove_header(&SG(sapi_headers).headers, sapi_header->header, strlen(sapi_header->header)); + sapi_remove_header(&SG(sapi_headers).headers, sapi_header->header, strlen(sapi_header->header), 0); *colon_offset = sav; } } @@ -668,7 +670,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) sapi_header_struct sapi_header; char *colon_offset; char *header_line; - size_t header_line_len; + size_t header_line_len, header_len; int http_response_code; if (SG(headers_sent) && !SG(request_info).no_headers) { @@ -691,6 +693,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) case SAPI_HEADER_ADD: case SAPI_HEADER_REPLACE: + case SAPI_HEADER_DELETE_PREFIX: case SAPI_HEADER_DELETE: { sapi_header_line *p = arg; @@ -699,7 +702,13 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) } header_line = estrndup(p->line, p->line_len); header_line_len = p->line_len; - http_response_code = p->response_code; + if (op == SAPI_HEADER_DELETE_PREFIX) { + header_len = p->header_len; + http_response_code = 0; + } else { + header_len = 0; + http_response_code = p->response_code; + } break; } @@ -722,8 +731,8 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) header_line[header_line_len]='\0'; } - if (op == SAPI_HEADER_DELETE) { - if (strchr(header_line, ':')) { + if (op == SAPI_HEADER_DELETE || op == SAPI_HEADER_DELETE_PREFIX) { + if (op == SAPI_HEADER_DELETE && strchr(header_line, ':')) { efree(header_line); sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon."); return FAILURE; @@ -733,7 +742,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) sapi_header.header_len = header_line_len; sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers)); } - sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len); + sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len, header_len); efree(header_line); return SUCCESS; } else { diff --git a/main/SAPI.h b/main/SAPI.h index 284f4cb96f1fa..f7a64f243104e 100644 --- a/main/SAPI.h +++ b/main/SAPI.h @@ -185,13 +185,17 @@ END_EXTERN_C() typedef struct { const char *line; /* If you allocated this, you need to free it yourself */ size_t line_len; - zend_long response_code; /* long due to zend_parse_parameters compatibility */ + union { + zend_long response_code; /* long due to zend_parse_parameters compatibility */ + size_t header_len; /* the "Key" in "Key: Value", for optimization */ + }; } sapi_header_line; typedef enum { /* Parameter: */ SAPI_HEADER_REPLACE, /* sapi_header_line* */ SAPI_HEADER_ADD, /* sapi_header_line* */ SAPI_HEADER_DELETE, /* sapi_header_line* */ + SAPI_HEADER_DELETE_PREFIX, /* sapi_header_line* */ SAPI_HEADER_DELETE_ALL, /* void */ SAPI_HEADER_SET_STATUS /* int */ } sapi_header_op_enum; @@ -199,7 +203,6 @@ typedef enum { /* Parameter: */ BEGIN_EXTERN_C() SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg); -/* Deprecated functions. Use sapi_header_op instead. */ SAPI_API int sapi_add_header_ex(const char *header_line, size_t header_line_len, bool duplicate, bool replace); #define sapi_add_header(a, b, c) sapi_add_header_ex((a),(b),(c),1) diff --git a/main/explicit_bzero.c b/main/explicit_bzero.c index 75cd126ee9a56..c49bdede66247 100644 --- a/main/explicit_bzero.c +++ b/main/explicit_bzero.c @@ -28,8 +28,10 @@ PHPAPI void php_explicit_bzero(void *dst, size_t siz) { -#ifdef HAVE_EXPLICIT_MEMSET - explicit_memset(dst, 0, siz); +#ifdef HAVE_MEMSET_EXPLICIT /* C23 */ + memset_explicit(dst, 0, siz); +#elif defined(HAVE_EXPLICIT_MEMSET) /* NetBSD-specific */ + explicit_memset(dst, 0, siz); #elif defined(PHP_WIN32) RtlSecureZeroMemory(dst, siz); #elif defined(__GNUC__) diff --git a/main/fopen_wrappers.h b/main/fopen_wrappers.h index f4070b11c3dec..1a1289836ba33 100644 --- a/main/fopen_wrappers.h +++ b/main/fopen_wrappers.h @@ -33,8 +33,6 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path /* OPENBASEDIR_CHECKPATH(filename) to ease merge between 6.x and 5.x */ #define OPENBASEDIR_CHECKPATH(filename) php_check_open_basedir(filename) -PHPAPI int php_check_safe_mode_include_dir(const char *path); - PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_len, const char *path); PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const char *path, zend_string **opened_path); diff --git a/main/main.c b/main/main.c index 18c8e2dfac7ec..db7de754143ac 100644 --- a/main/main.c +++ b/main/main.c @@ -51,6 +51,10 @@ #include "ext/date/php_date.h" #include "ext/random/php_random_csprng.h" #include "ext/random/php_random_zend_utils.h" +#include "ext/opcache/ZendAccelerator.h" +#ifdef HAVE_JIT +# include "ext/opcache/jit/zend_jit.h" +#endif #include "php_variables.h" #include "ext/standard/credits.h" #ifdef PHP_WIN32 @@ -332,6 +336,22 @@ static PHP_INI_MH(OnChangeMemoryLimit) } else { value = Z_L(1)<<30; /* effectively, no limit */ } + + /* If memory_limit exceeds max_memory_limit, warn and set to max_memory_limit instead. */ + if (value > PG(max_memory_limit)) { + if (value != -1) { + zend_error(E_WARNING, + "Failed to set memory_limit to %zd bytes. Setting to max_memory_limit instead (currently: " ZEND_LONG_FMT " bytes)", + value, PG(max_memory_limit)); + } + + zend_ini_entry *max_mem_limit_ini = zend_hash_str_find_ptr(EG(ini_directives), ZEND_STRL("max_memory_limit")); + entry->value = zend_string_copy(max_mem_limit_ini->value); + PG(memory_limit) = PG(max_memory_limit); + + return SUCCESS; + } + if (zend_set_memory_limit(value) == FAILURE) { /* When the memory limit is reset to the original level during deactivation, we may be * using more memory than the original limit while shutdown is still in progress. @@ -347,6 +367,26 @@ static PHP_INI_MH(OnChangeMemoryLimit) } /* }}} */ +static PHP_INI_MH(OnChangeMaxMemoryLimit) +{ + size_t value; + if (new_value) { + value = zend_ini_parse_uquantity_warn(new_value, entry->name); + } else { + value = Z_L(1) << 30; /* effectively, no limit */ + } + + if (zend_set_memory_limit(value) == FAILURE) { + zend_error(E_ERROR, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true)); + return FAILURE; + } + + PG(memory_limit) = value; + PG(max_memory_limit) = value; + + return SUCCESS; +} + /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnSetLogFilter) { @@ -373,41 +413,6 @@ static PHP_INI_MH(OnSetLogFilter) } /* }}} */ -/* {{{ php_disable_classes */ -static void php_disable_classes(void) -{ - char *s = NULL, *e; - - if (!*(INI_STR("disable_classes"))) { - return; - } - - e = PG(disable_classes) = strdup(INI_STR("disable_classes")); - - while (*e) { - switch (*e) { - case ' ': - case ',': - if (s) { - *e = '\0'; - zend_disable_class(s, e-s); - s = NULL; - } - break; - default: - if (!s) { - s = e; - } - break; - } - e++; - } - if (s) { - zend_disable_class(s, e-s); - } -} -/* }}} */ - /* {{{ php_binary_init */ static void php_binary_init(void) { @@ -658,6 +663,19 @@ static PHP_INI_MH(OnUpdateInputEncoding) } /* }}} */ +static PHP_INI_MH(OnUpdateReportMemleaks) +{ + bool *p = (bool *) ZEND_INI_GET_ADDR(); + bool new_bool_value = zend_ini_parse_bool(new_value); + + if (!new_bool_value) { + php_error_docref(NULL, E_DEPRECATED, "Directive 'report_memleaks' is deprecated"); + } + + *p = new_bool_value; + return SUCCESS; +} + /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnUpdateOutputEncoding) { @@ -677,7 +695,7 @@ static PHP_INI_MH(OnUpdateOutputEncoding) /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnUpdateErrorLog) { - /* Only do the safemode/open_basedir check at runtime */ + /* Only do the open_basedir check at runtime */ if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value && zend_string_equals_literal(new_value, "syslog")) { if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) { @@ -692,7 +710,7 @@ static PHP_INI_MH(OnUpdateErrorLog) /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnUpdateMailLog) { - /* Only do the safemode/open_basedir check at runtime */ + /* Only do the open_basedir check at runtime */ if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value) { if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) { return FAILURE; @@ -703,11 +721,40 @@ static PHP_INI_MH(OnUpdateMailLog) } /* }}} */ +/* {{{ PHP_INI_MH */ +static PHP_INI_MH(OnUpdateMailCrLfMode) +{ + if (new_value) { + if (ZSTR_LEN(new_value) > 0 && + !zend_string_equals_literal(new_value, "crlf") && + !zend_string_equals_literal(new_value, "lf") && + !zend_string_equals_literal(new_value, "mixed") && + !zend_string_equals_literal(new_value, "os")) { + int err_type; + + if (stage == ZEND_INI_STAGE_RUNTIME) { + err_type = E_WARNING; + } else { + err_type = E_ERROR; + } + + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + php_error_docref(NULL, err_type, "Invalid value \"%s\" for mail.cr_lf_mode. Must be one of: \"crlf\", \"lf\", \"mixed\", \"os\"", ZSTR_VAL(new_value)); + } + + return FAILURE; + } + } + OnUpdateStr(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + return SUCCESS; +} +/* }}} */ + /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnChangeMailForceExtra) { /* Check that INI setting does not have any nul bytes */ - if (new_value && ZSTR_LEN(new_value) != strlen(ZSTR_VAL(new_value))) { + if (new_value && zend_str_has_nul_byte(new_value)) { /* TODO Emit warning? */ return FAILURE; } @@ -761,11 +808,11 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("log_errors", "0", PHP_INI_ALL, OnUpdateBool, log_errors, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("ignore_repeated_errors", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_errors, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("ignore_repeated_source", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_source, php_core_globals, core_globals) - STD_PHP_INI_BOOLEAN("report_memleaks", "1", PHP_INI_ALL, OnUpdateBool, report_memleaks, php_core_globals, core_globals) + STD_PHP_INI_BOOLEAN("report_memleaks", "1", PHP_INI_ALL, OnUpdateReportMemleaks, report_memleaks, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("report_zend_debug", "0", PHP_INI_ALL, OnUpdateBool, report_zend_debug, php_core_globals, core_globals) STD_PHP_INI_ENTRY("output_buffering", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateLong, output_buffering, php_core_globals, core_globals) STD_PHP_INI_ENTRY("output_handler", NULL, PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, output_handler, php_core_globals, core_globals) - STD_PHP_INI_BOOLEAN("register_argc_argv", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_argc_argv, php_core_globals, core_globals) + STD_PHP_INI_BOOLEAN("register_argc_argv", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, register_argc_argv, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals) @@ -808,15 +855,18 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL) STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("mail.mixed_lf_and_crlf", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_mixed_lf_and_crlf, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("mail.cr_lf_mode", "crlf", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailCrLfMode, mail_cr_lf_mode, php_core_globals, core_globals) STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailLog, mail_log, php_core_globals, core_globals) PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, OnChangeBrowscap) - PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit) + + PHP_INI_ENTRY("max_memory_limit", "-1", PHP_INI_SYSTEM, OnChangeMaxMemoryLimit) + PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit) + PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision) PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL) PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("mail.force_extra_parameters",NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnChangeMailForceExtra) PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL) - PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL) PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) PHP_INI_ENTRY("max_multipart_body_parts", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL) @@ -1010,7 +1060,7 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ const char *space = ""; const char *class_name = ""; const char *function; - int origin_len; + size_t origin_len; char *origin; zend_string *message; int is_function = 0; @@ -1077,9 +1127,10 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ /* if we still have memory then format the origin */ if (is_function) { - origin_len = (int)spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params); + origin_len = spprintf(&origin, 0, "%s%s%s(%s)", class_name, space, function, params); } else { - origin_len = (int)spprintf(&origin, 0, "%s", function); + origin_len = strlen(function); + origin = estrndup(function, origin_len); } if (PG(html_errors)) { @@ -1096,14 +1147,14 @@ PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int typ /* no docref given but function is known (the default) */ if (!docref && is_function) { - int doclen; + size_t doclen; while (*function == '_') { function++; } if (space[0] == '\0') { - doclen = (int)spprintf(&docref_buf, 0, "function.%s", function); + doclen = spprintf(&docref_buf, 0, "function.%s", function); } else { - doclen = (int)spprintf(&docref_buf, 0, "%s.%s", class_name, function); + doclen = spprintf(&docref_buf, 0, "%s.%s", class_name, function); } while((p = strchr(docref_buf, '_')) != NULL) { *p = '-'; @@ -1317,10 +1368,10 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c case E_CORE_WARNING: case E_COMPILE_WARNING: case E_USER_WARNING: - /* throw an exception if we are in EH_THROW mode and the type is warning. - * fatal errors are real errors and cannot be made exceptions. - * exclude deprecated for the sake of BC to old damaged code. - * notices are no errors and are not treated as such like E_WARNINGS. + /* Throw an exception if we are in EH_THROW mode and the type is warning. + * Fatal errors are real errors and cannot be made exceptions. + * Exclude deprecated for the sake of BC to old damaged code. + * Notices are not errors and are not treated as such like E_WARNINGS. * DO NOT overwrite a pending exception. */ if (!EG(exception)) { @@ -1577,24 +1628,16 @@ PHPAPI char *php_get_current_user(void) PHP_FUNCTION(set_time_limit) { zend_long new_timeout; - char *new_timeout_str; - size_t new_timeout_strlen; - zend_string *key; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &new_timeout) == FAILURE) { RETURN_THROWS(); } - new_timeout_strlen = zend_spprintf(&new_timeout_str, 0, ZEND_LONG_FMT, new_timeout); - - key = ZSTR_INIT_LITERAL("max_execution_time", 0); - if (zend_alter_ini_entry_chars_ex(key, new_timeout_str, new_timeout_strlen, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == SUCCESS) { - RETVAL_TRUE; - } else { - RETVAL_FALSE; - } - zend_string_release_ex(key, 0); - efree(new_timeout_str); + zend_string *time = zend_long_to_str(new_timeout); + zend_string *key = ZSTR_INIT_LITERAL("max_execution_time", false); + RETVAL_BOOL(zend_alter_ini_entry_ex(key, time, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, false) == SUCCESS); + zend_string_release_ex(key, false); + zend_string_release_ex(time, false); } /* }}} */ @@ -1816,6 +1859,12 @@ static void sigchld_handler(int apar) /* }}} */ #endif +PHPAPI void php_child_init(void) +{ + refresh_memory_manager(); + zend_max_execution_timer_init(); +} + /* {{{ php_request_startup */ zend_result php_request_startup(void) { @@ -2050,9 +2099,6 @@ static void core_globals_dtor(php_core_globals *core_globals) ZEND_ASSERT(!core_globals->last_error_message); ZEND_ASSERT(!core_globals->last_error_file); - if (core_globals->disable_classes) { - free(core_globals->disable_classes); - } if (core_globals->php_binary) { free(core_globals->php_binary); } @@ -2236,9 +2282,7 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi load zend extensions and register php function extensions to be loaded later */ zend_stream_init(); - if (php_init_config() == FAILURE) { - return FAILURE; - } + php_init_config(); zend_stream_shutdown(); /* Register PHP core ini entries */ @@ -2319,9 +2363,8 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi } } - /* disable certain classes and functions as requested by php.ini */ + /* disable certain functions as requested by php.ini */ zend_disable_functions(INI_STR("disable_functions")); - php_disable_classes(); /* make core report what it should */ if ((module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core")-1)) != NULL) { @@ -2350,7 +2393,7 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi struct { const long error_level; const char *phrase; - const char *directives[18]; /* Remember to change this if the number of directives change */ + const char *directives[19]; /* Remember to change this if the number of directives change */ } directives[2] = { { E_DEPRECATED, @@ -2381,6 +2424,7 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi "safe_mode_protected_env_vars", "zend.ze1_compatibility_mode", "track_errors", + "disable_classes", NULL } } @@ -2767,7 +2811,12 @@ PHPAPI void php_reserve_tsrm_memory(void) TSRM_ALIGNED_SIZE(zend_mm_globals_size()) + TSRM_ALIGNED_SIZE(zend_gc_globals_size()) + TSRM_ALIGNED_SIZE(sizeof(php_core_globals)) + - TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct)) + TSRM_ALIGNED_SIZE(sizeof(sapi_globals_struct)) + + TSRM_ALIGNED_SIZE(sizeof(zend_accel_globals)) + +#ifdef HAVE_JIT + TSRM_ALIGNED_SIZE(sizeof(zend_jit_globals)) + +#endif + 0 ); } /* }}} */ diff --git a/main/main.stub.php b/main/main.stub.php index 3359d4a1cd0bf..2732ccd290fa4 100644 --- a/main/main.stub.php +++ b/main/main.stub.php @@ -41,6 +41,14 @@ */ const PHP_BUILD_DATE = UNKNOWN; +#ifdef PHP_BUILD_PROVIDER +/** + * @var string + * @cvalue PHP_BUILD_PROVIDER + */ +const PHP_BUILD_PROVIDER = UNKNOWN; +#endif + /** * @var bool * @cvalue PHP_ZTS diff --git a/main/main_arginfo.h b/main/main_arginfo.h index 922af3aff0629..3aa0b07e42c87 100644 --- a/main/main_arginfo.h +++ b/main/main_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: cb5c9a3e48b18a773264378099267550ca9e4fc1 */ + * Stub hash: e8b81aa6f03d36f35def2bb1fcc3563b284a113b */ static void register_main_symbols(int module_number) { @@ -10,6 +10,9 @@ static void register_main_symbols(int module_number) REGISTER_STRING_CONSTANT("PHP_EXTRA_VERSION", PHP_EXTRA_VERSION, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHP_VERSION_ID", PHP_VERSION_ID, CONST_PERSISTENT); REGISTER_STRING_CONSTANT("PHP_BUILD_DATE", php_build_date, CONST_PERSISTENT); +#if defined(PHP_BUILD_PROVIDER) + REGISTER_STRING_CONSTANT("PHP_BUILD_PROVIDER", PHP_BUILD_PROVIDER, CONST_PERSISTENT); +#endif REGISTER_BOOL_CONSTANT("PHP_ZTS", PHP_ZTS, CONST_PERSISTENT); REGISTER_BOOL_CONSTANT("PHP_DEBUG", PHP_DEBUG, CONST_PERSISTENT); REGISTER_STRING_CONSTANT("PHP_OS", PHP_OS_STR, CONST_PERSISTENT); diff --git a/main/network.c b/main/network.c index 14f4ca4dff987..70dc505582868 100644 --- a/main/network.c +++ b/main/network.c @@ -1109,7 +1109,7 @@ PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0); memset(sock, 0, sizeof(php_netstream_data_t)); - sock->is_blocked = 1; + sock->is_blocked = true; sock->timeout.tv_sec = FG(default_socket_timeout); sock->timeout.tv_usec = 0; sock->socket = socket; diff --git a/main/output.c b/main/output.c index ef6be672d1c16..c75b09e86c18b 100644 --- a/main/output.c +++ b/main/output.c @@ -934,6 +934,14 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl return PHP_OUTPUT_HANDLER_FAILURE; } + /* php_output_lock_error() doesn't fail for PHP_OUTPUT_HANDLER_WRITE but + * anything that gets written will silently be discarded, remember that we + * tried to write so a deprecation warning can be emitted at the end. */ + if (context->op == PHP_OUTPUT_HANDLER_WRITE && OG(active) && OG(running)) { + handler->flags |= PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT; + } + + bool still_have_handler = true; /* storable? */ if (php_output_handler_append(handler, &context->in) && !context->op) { context->op = original_op; @@ -948,6 +956,7 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl if (handler->flags & PHP_OUTPUT_HANDLER_USER) { zval ob_args[2]; zval retval; + ZVAL_UNDEF(&retval); /* ob_data */ ZVAL_STRINGL(&ob_args[0], handler->buffer.data, handler->buffer.used); @@ -959,17 +968,69 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl handler->func.user->fci.params = ob_args; handler->func.user->fci.retval = &retval; -#define PHP_OUTPUT_USER_SUCCESS(retval) ((Z_TYPE(retval) != IS_UNDEF) && !(Z_TYPE(retval) == IS_FALSE)) - if (SUCCESS == zend_call_function(&handler->func.user->fci, &handler->func.user->fcc) && PHP_OUTPUT_USER_SUCCESS(retval)) { - /* user handler may have returned TRUE */ - status = PHP_OUTPUT_HANDLER_NO_DATA; - if (Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) { - convert_to_string(&retval); - if (Z_STRLEN(retval)) { - context->out.data = estrndup(Z_STRVAL(retval), Z_STRLEN(retval)); - context->out.used = Z_STRLEN(retval); - context->out.free = 1; - status = PHP_OUTPUT_HANDLER_SUCCESS; + if (SUCCESS == zend_call_function(&handler->func.user->fci, &handler->func.user->fcc) && Z_TYPE(retval) != IS_UNDEF) { + if (Z_TYPE(retval) != IS_STRING || handler->flags & PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT) { + // Make sure that we don't get lost in the current output buffer + // by disabling it + handler->flags |= PHP_OUTPUT_HANDLER_DISABLED; + // Make sure we keep a reference to the handler name in + // case + // * The handler produced output *and* returned a non-string + // * The first deprecation message causes the handler to + // be removed + zend_string *handler_name = handler->name; + zend_string_addref(handler_name); + if (handler->flags & PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT) { + // The handler might not always produce output + handler->flags &= ~PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT; + php_error_docref( + NULL, + E_DEPRECATED, + "Producing output from user output handler %s is deprecated", + ZSTR_VAL(handler_name) + ); + } + if (Z_TYPE(retval) != IS_STRING) { + php_error_docref( + NULL, + E_DEPRECATED, + "Returning a non-string result from user output handler %s is deprecated", + ZSTR_VAL(handler_name) + ); + } + zend_string_release(handler_name); + + // Check if the handler is still in the list of handlers to + // determine if the PHP_OUTPUT_HANDLER_DISABLED flag can + // be removed + still_have_handler = false; + int handler_count = php_output_get_level(); + if (handler_count) { + php_output_handler **handlers = (php_output_handler **) zend_stack_base(&OG(handlers)); + for (int handler_num = 0; handler_num < handler_count; ++handler_num) { + php_output_handler *curr_handler = handlers[handler_num]; + if (curr_handler == handler) { + handler->flags &= (~PHP_OUTPUT_HANDLER_DISABLED); + still_have_handler = true; + break; + } + } + } + } + if (Z_TYPE(retval) == IS_FALSE) { + /* call failed, pass internal buffer along */ + status = PHP_OUTPUT_HANDLER_FAILURE; + } else { + /* user handler may have returned TRUE */ + status = PHP_OUTPUT_HANDLER_NO_DATA; + if (Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) { + convert_to_string(&retval); + if (Z_STRLEN(retval)) { + context->out.data = estrndup(Z_STRVAL(retval), Z_STRLEN(retval)); + context->out.used = Z_STRLEN(retval); + context->out.free = 1; + status = PHP_OUTPUT_HANDLER_SUCCESS; + } } } } else { @@ -996,10 +1057,17 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl status = PHP_OUTPUT_HANDLER_FAILURE; } } - handler->flags |= PHP_OUTPUT_HANDLER_STARTED; + if (still_have_handler) { + handler->flags |= PHP_OUTPUT_HANDLER_STARTED; + } OG(running) = NULL; } + if (!still_have_handler) { + // Handler and context will have both already been freed + return status; + } + switch (status) { case PHP_OUTPUT_HANDLER_FAILURE: /* disable this handler */ @@ -1225,6 +1293,19 @@ static int php_output_stack_pop(int flags) } php_output_handler_op(orphan, &context); } + // If it isn't still in the stack, cannot free it + bool still_have_handler = false; + int handler_count = php_output_get_level(); + if (handler_count) { + php_output_handler **handlers = (php_output_handler **) zend_stack_base(&OG(handlers)); + for (int handler_num = 0; handler_num < handler_count; ++handler_num) { + php_output_handler *curr_handler = handlers[handler_num]; + if (curr_handler == orphan) { + still_have_handler = true; + break; + } + } + } /* pop it off the stack */ zend_stack_del_top(&OG(handlers)); @@ -1240,7 +1321,9 @@ static int php_output_stack_pop(int flags) } /* destroy the handler (after write!) */ - php_output_handler_free(&orphan); + if (still_have_handler) { + php_output_handler_free(&orphan); + } php_output_context_dtor(&context); return 1; diff --git a/main/php_compat.h b/main/php_compat.h index 438ada44eda03..2f9f4c1c89e62 100644 --- a/main/php_compat.h +++ b/main/php_compat.h @@ -393,8 +393,4 @@ #define XML_NS 1 #endif -#ifdef PHP_EXPORTS -#define PCRE_STATIC -#endif - #endif diff --git a/main/php_glob.c b/main/php_glob.c index 8757ec0783f6d..8edfb8326da41 100644 --- a/main/php_glob.c +++ b/main/php_glob.c @@ -266,7 +266,7 @@ PHPAPI int php_glob(const char *pattern, int flags, int (*errfunc)(const char *, pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; - if (strnlen(pattern, PATH_MAX) == PATH_MAX) + if (zend_strnlen(pattern, PATH_MAX) == PATH_MAX) return(PHP_GLOB_NOMATCH); if (pglob->gl_offs >= SSIZE_MAX || pglob->gl_pathc >= SSIZE_MAX || diff --git a/main/php_globals.h b/main/php_globals.h index ab7a9a00b2f1d..893bf25d26cb5 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -72,6 +72,7 @@ struct _php_core_globals { zend_long serialize_precision; zend_long memory_limit; + zend_long max_memory_limit; zend_long max_input_time; char *error_log; @@ -142,7 +143,6 @@ struct _php_core_globals { char *php_sys_temp_dir; - char *disable_classes; zend_long max_input_nesting_level; zend_long max_input_vars; @@ -152,6 +152,7 @@ struct _php_core_globals { char *request_order; char *mail_log; + zend_string *mail_cr_lf_mode; bool mail_x_header; bool mail_mixed_lf_and_crlf; diff --git a/main/php_ini.c b/main/php_ini.c index 8d0fdfdf72d74..e464c05d1fcc1 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -21,7 +21,6 @@ #include "php_ini.h" #include "ext/standard/dl.h" #include "zend_extensions.h" -#include "zend_highlight.h" #include "SAPI.h" #include "php_main.h" #include "php_scandir.h" @@ -49,17 +48,17 @@ #endif -typedef struct _php_extension_lists { +typedef struct php_extension_lists { zend_llist engine; zend_llist functions; } php_extension_lists; /* True globals */ -static int is_special_section = 0; +static bool is_special_section = false; static HashTable *active_ini_hash; static HashTable configuration_hash; -static int has_per_dir_config = 0; -static int has_per_host_config = 0; +static bool has_per_dir_config = false; +static bool has_per_host_config = false; PHPAPI char *php_ini_opened_path=NULL; static php_extension_lists extension_lists; PHPAPI char *php_ini_scanned_path=NULL; @@ -175,7 +174,7 @@ PHPAPI void config_zval_dtor(zval *zvalue) /* Reset / free active_ini_section global */ #define RESET_ACTIVE_INI_HASH() do { \ active_ini_hash = NULL; \ - is_special_section = 0; \ + is_special_section = false; \ } while (0) /* }}} */ @@ -211,7 +210,7 @@ static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_t } else { /* Store in active hash */ entry = zend_hash_update(active_hash, Z_STR_P(arg1), arg2); - Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), 1); + Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), true); } } break; @@ -230,7 +229,7 @@ static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_t /* If option not found in hash or is not an array -> create array, otherwise add to existing array */ if ((find_arr = zend_hash_find(active_hash, Z_STR_P(arg1))) == NULL || Z_TYPE_P(find_arr) != IS_ARRAY) { ZVAL_NEW_PERSISTENT_ARR(&option_arr); - zend_hash_init(Z_ARRVAL(option_arr), 8, NULL, config_zval_dtor, 1); + zend_hash_init(Z_ARRVAL(option_arr), 8, NULL, config_zval_dtor, true); find_arr = zend_hash_update(active_hash, Z_STR_P(arg1), &option_arr); } @@ -240,7 +239,7 @@ static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_t } else { entry = zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2); } - Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), 1); + Z_STR_P(entry) = zend_string_dup(Z_STR_P(entry), true); } break; @@ -252,27 +251,27 @@ static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_t size_t key_len; /* PATH sections */ - if (!zend_binary_strncasecmp(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), "PATH", sizeof("PATH") - 1, sizeof("PATH") - 1)) { + if (zend_string_starts_with_literal_ci(Z_STR_P(arg1), "PATH")) { key = Z_STRVAL_P(arg1); key = key + sizeof("PATH") - 1; key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1; - is_special_section = 1; - has_per_dir_config = 1; + is_special_section = true; + has_per_dir_config = true; /* make the path lowercase on Windows, for case insensitivity. Does nothing for other platforms */ TRANSLATE_SLASHES_LOWER(key); /* HOST sections */ - } else if (!zend_binary_strncasecmp(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), "HOST", sizeof("HOST") - 1, sizeof("HOST") - 1)) { + } else if (zend_string_starts_with_literal_ci(Z_STR_P(arg1), "HOST")) { key = Z_STRVAL_P(arg1); key = key + sizeof("HOST") - 1; key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1; - is_special_section = 1; - has_per_host_config = 1; + is_special_section = true; + has_per_host_config = true; zend_str_tolower(key, key_len); /* host names are case-insensitive. */ } else { - is_special_section = 0; + is_special_section = false; } if (key && key_len > 0) { @@ -297,7 +296,7 @@ static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_t zval section_arr; ZVAL_NEW_PERSISTENT_ARR(§ion_arr); - zend_hash_init(Z_ARRVAL(section_arr), 8, NULL, (dtor_func_t) config_zval_dtor, 1); + zend_hash_init(Z_ARRVAL(section_arr), 8, NULL, (dtor_func_t) config_zval_dtor, true); entry = zend_hash_str_update(target_hash, key, key_len, §ion_arr); } if (Z_TYPE_P(entry) == IS_ARRAY) { @@ -407,30 +406,30 @@ static void append_ini_path(char *php_ini_search_path, size_t search_path_size, } /* {{{ php_init_config */ -int php_init_config(void) +void php_init_config(void) { char *php_ini_file_name = NULL; char *php_ini_search_path = NULL; - int php_ini_scanned_path_len; + size_t php_ini_scanned_path_len; char *open_basedir; - int free_ini_search_path = 0; + bool free_ini_search_path = false; zend_string *opened_path = NULL; - zend_hash_init(&configuration_hash, 8, NULL, config_zval_dtor, 1); + zend_hash_init(&configuration_hash, 8, NULL, config_zval_dtor, true); if (sapi_module.ini_defaults) { sapi_module.ini_defaults(&configuration_hash); } - zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1); - zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, 1); + zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, true); + zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, true); open_basedir = PG(open_basedir); if (sapi_module.php_ini_path_override) { php_ini_file_name = sapi_module.php_ini_path_override; php_ini_search_path = sapi_module.php_ini_path_override; - free_ini_search_path = 0; + free_ini_search_path = false; } else if (!sapi_module.php_ini_ignore) { size_t search_path_size; char *default_location; @@ -480,7 +479,7 @@ int php_init_config(void) search_path_size = MAXPATHLEN * 4 + strlen(env_location) + 3 + 1; php_ini_search_path = (char *) emalloc(search_path_size); - free_ini_search_path = 1; + free_ini_search_path = true; php_ini_search_path[0] = 0; /* Add environment location */ @@ -601,15 +600,15 @@ int php_init_config(void) zend_stream_init_fp(&fh, fp, filename); RESET_ACTIVE_INI_HASH(); - zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash); + zend_parse_ini_file(&fh, true, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash); { zval tmp; - ZVAL_NEW_STR(&tmp, zend_string_init(filename, strlen(filename), 1)); + ZVAL_NEW_STR(&tmp, zend_string_init(filename, strlen(filename), true)); zend_hash_str_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path")-1, &tmp); if (opened_path) { - zend_string_release_ex(opened_path, 0); + zend_string_release_ex(opened_path, false); } php_ini_opened_path = zend_strndup(Z_STRVAL(tmp), Z_STRLEN(tmp)); } @@ -626,22 +625,20 @@ int php_init_config(void) /* Or fall back using possible --with-config-file-scan-dir setting (defaults to empty string!) */ php_ini_scanned_path = PHP_CONFIG_FILE_SCAN_DIR; } - php_ini_scanned_path_len = (int)strlen(php_ini_scanned_path); + php_ini_scanned_path_len = strlen(php_ini_scanned_path); /* Scan and parse any .ini files found in scan path if path not empty. */ if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) { struct dirent **namelist; - int ndir, i; zend_stat_t sb = {0}; char ini_file[MAXPATHLEN]; char *p; zend_llist scanned_ini_list; - zend_llist_element *element; - int l, total_l = 0; + size_t total_l = 0; char *bufpath, *debpath, *endpath; - int lenpath; + size_t lenpath; - zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1); + zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, true); bufpath = estrdup(php_ini_scanned_path); for (debpath = bufpath ; debpath ; debpath=endpath) { @@ -654,11 +651,11 @@ int php_init_config(void) to allow "/foo/php.d:" or ":/foo/php.d" */ debpath = PHP_CONFIG_FILE_SCAN_DIR; } - lenpath = (int)strlen(debpath); + lenpath = strlen(debpath); - if (lenpath > 0 && (ndir = php_scandir(debpath, &namelist, 0, php_alphasort)) > 0) { - - for (i = 0; i < ndir; i++) { + int ndir; + if (lenpath > 0 && (ndir = php_scandir(debpath, &namelist, NULL, php_alphasort)) > 0) { + for (int i = 0; i < ndir; i++) { /* check for any file with .ini extension */ if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) { @@ -679,9 +676,9 @@ int php_init_config(void) FILE *file = VCWD_FOPEN(ini_file, "r"); if (file) { zend_stream_init_fp(&fh, file, ini_file); - if (zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash) == SUCCESS) { + if (zend_parse_ini_file(&fh, true, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash) == SUCCESS) { /* Here, add it to the list of ini files read */ - l = (int)strlen(ini_file); + size_t l = strlen(ini_file); total_l += l + 2; p = estrndup(ini_file, l); zend_llist_add_element(&scanned_ini_list, &p); @@ -698,13 +695,13 @@ int php_init_config(void) efree(bufpath); if (total_l) { - int php_ini_scanned_files_len = (php_ini_scanned_files) ? (int)strlen(php_ini_scanned_files) + 1 : 0; + size_t php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0; php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1); if (!php_ini_scanned_files_len) { *php_ini_scanned_files = '\0'; } total_l += php_ini_scanned_files_len; - for (element = scanned_ini_list.head; element; element = element->next) { + for (zend_llist_element *element = scanned_ini_list.head; element; element = element->next) { if (php_ini_scanned_files_len) { strlcat(php_ini_scanned_files, ",\n", total_l); } @@ -721,15 +718,13 @@ int php_init_config(void) if (sapi_module.ini_entries) { /* Reset active ini section */ RESET_ACTIVE_INI_HASH(); - zend_parse_ini_string(sapi_module.ini_entries, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash); + zend_parse_ini_string(sapi_module.ini_entries, true, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash); } - - return SUCCESS; } /* }}} */ /* {{{ php_shutdown_config */ -int php_shutdown_config(void) +void php_shutdown_config(void) { zend_hash_destroy(&configuration_hash); if (php_ini_opened_path) { @@ -740,7 +735,6 @@ int php_shutdown_config(void) free(php_ini_scanned_files); php_ini_scanned_files = NULL; } - return SUCCESS; } /* }}} */ @@ -756,7 +750,7 @@ void php_ini_register_extensions(void) /* }}} */ /* {{{ php_parse_user_ini_file */ -PHPAPI int php_parse_user_ini_file(const char *dirname, const char *ini_filename, HashTable *target_hash) +PHPAPI zend_result php_parse_user_ini_file(const char *dirname, const char *ini_filename, HashTable *target_hash) { zend_stat_t sb = {0}; char ini_file[MAXPATHLEN]; @@ -766,7 +760,7 @@ PHPAPI int php_parse_user_ini_file(const char *dirname, const char *ini_filename if (VCWD_STAT(ini_file, &sb) == 0) { if (S_ISREG(sb.st_mode)) { zend_file_handle fh; - int ret = FAILURE; + zend_result ret = FAILURE; zend_stream_init_fp(&fh, VCWD_FOPEN(ini_file, "r"), ini_file); if (fh.handle.fp) { @@ -780,7 +774,7 @@ PHPAPI int php_parse_user_ini_file(const char *dirname, const char *ini_filename bool orig_rc_debug = zend_rc_debug; zend_rc_debug = false; #endif - ret = zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, target_hash); + ret = zend_parse_ini_file(&fh, true, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, target_hash); #if ZEND_RC_DEBUG zend_rc_debug = orig_rc_debug; #endif @@ -797,22 +791,22 @@ PHPAPI int php_parse_user_ini_file(const char *dirname, const char *ini_filename /* }}} */ /* {{{ php_ini_activate_config */ -PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage) +PHPAPI void php_ini_activate_config(const HashTable *source_hash, int modify_type, int stage) { zend_string *str; zval *data; /* Walk through config hash and alter matching ini entries using the values found in the hash */ ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(source_hash, str, data) { - zend_string *data_str = zend_string_dup(Z_STR_P(data), 0); - zend_alter_ini_entry_ex(str, data_str, modify_type, stage, 0); + zend_string *data_str = zend_string_dup(Z_STR_P(data), false); + zend_alter_ini_entry_ex(str, data_str, modify_type, stage, false); zend_string_release(data_str); } ZEND_HASH_FOREACH_END(); } /* }}} */ /* {{{ php_ini_has_per_dir_config */ -PHPAPI int php_ini_has_per_dir_config(void) +PHPAPI bool php_ini_has_per_dir_config(void) { return has_per_dir_config; } @@ -861,7 +855,7 @@ PHPAPI void php_ini_activate_per_dir_config(char *path, size_t path_len) /* }}} */ /* {{{ php_ini_has_per_host_config */ -PHPAPI int php_ini_has_per_host_config(void) +PHPAPI bool php_ini_has_per_host_config(void) { return has_per_host_config; } @@ -896,7 +890,7 @@ PHPAPI zval *cfg_get_entry(const char *name, size_t name_length) /* }}} */ /* {{{ cfg_get_long */ -PHPAPI int cfg_get_long(const char *varname, zend_long *result) +PHPAPI zend_result cfg_get_long(const char *varname, zend_long *result) { zval *tmp; @@ -910,7 +904,7 @@ PHPAPI int cfg_get_long(const char *varname, zend_long *result) /* }}} */ /* {{{ cfg_get_double */ -PHPAPI int cfg_get_double(const char *varname, double *result) +PHPAPI zend_result cfg_get_double(const char *varname, double *result) { zval *tmp; @@ -924,7 +918,7 @@ PHPAPI int cfg_get_double(const char *varname, double *result) /* }}} */ /* {{{ cfg_get_string */ -PHPAPI int cfg_get_string(const char *varname, char **result) +PHPAPI zend_result cfg_get_string(const char *varname, char **result) { zval *tmp; diff --git a/main/php_ini.h b/main/php_ini.h index a5538efd70766..4253ce43fbe11 100644 --- a/main/php_ini.h +++ b/main/php_ini.h @@ -21,18 +21,18 @@ BEGIN_EXTERN_C() PHPAPI void config_zval_dtor(zval *zvalue); -int php_init_config(void); -int php_shutdown_config(void); +void php_init_config(void); +void php_shutdown_config(void); void php_ini_register_extensions(void); PHPAPI zval *cfg_get_entry_ex(zend_string *name); PHPAPI zval *cfg_get_entry(const char *name, size_t name_length); -PHPAPI int cfg_get_long(const char *varname, zend_long *result); -PHPAPI int cfg_get_double(const char *varname, double *result); -PHPAPI int cfg_get_string(const char *varname, char **result); -PHPAPI int php_parse_user_ini_file(const char *dirname, const char *ini_filename, HashTable *target_hash); -PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage); -PHPAPI int php_ini_has_per_dir_config(void); -PHPAPI int php_ini_has_per_host_config(void); +PHPAPI zend_result cfg_get_long(const char *varname, zend_long *result); +PHPAPI zend_result cfg_get_double(const char *varname, double *result); +PHPAPI zend_result cfg_get_string(const char *varname, char **result); +PHPAPI zend_result php_parse_user_ini_file(const char *dirname, const char *ini_filename, HashTable *target_hash); +PHPAPI void php_ini_activate_config(const HashTable *source_hash, int modify_type, int stage); +PHPAPI bool php_ini_has_per_dir_config(void); +PHPAPI bool php_ini_has_per_host_config(void); PHPAPI void php_ini_activate_per_dir_config(char *path, size_t path_len); PHPAPI void php_ini_activate_per_host_config(const char *host, size_t host_len); PHPAPI HashTable* php_ini_get_configuration_hash(void); diff --git a/main/php_main.h b/main/php_main.h index a5b049487db23..bd28a0dee1d7f 100644 --- a/main/php_main.h +++ b/main/php_main.h @@ -49,6 +49,7 @@ ZEND_ATTRIBUTE_CONST PHPAPI const char *php_build_provider(void); PHPAPI char *php_get_version(sapi_module_struct *sapi_module); PHPAPI void php_print_version(sapi_module_struct *sapi_module); +PHPAPI void php_child_init(void); PHPAPI zend_result php_request_startup(void); PHPAPI void php_request_shutdown(void *dummy); PHPAPI zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module); diff --git a/main/php_network.h b/main/php_network.h index 94a2508c89e52..1d941265bd9a4 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -313,9 +313,9 @@ END_EXTERN_C() struct _php_netstream_data_t { php_socket_t socket; - char is_blocked; + bool is_blocked; + bool timeout_event; struct timeval timeout; - char timeout_event; size_t ownsize; }; typedef struct _php_netstream_data_t php_netstream_data_t; diff --git a/main/php_open_temporary_file.c b/main/php_open_temporary_file.c index b45537935a570..3a410eb7fa2d0 100644 --- a/main/php_open_temporary_file.c +++ b/main/php_open_temporary_file.c @@ -186,6 +186,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st free(random_prefix_w); efree(random_prefix); efree(new_state.cwd); + free(opened_path); return -1; } assert(strlen(opened_path) == opened_path_len); diff --git a/main/php_output.h b/main/php_output.h index 55bf62f62237a..896f1e0a8fea3 100644 --- a/main/php_output.h +++ b/main/php_output.h @@ -42,6 +42,7 @@ #define PHP_OUTPUT_HANDLER_STARTED 0x1000 #define PHP_OUTPUT_HANDLER_DISABLED 0x2000 #define PHP_OUTPUT_HANDLER_PROCESSED 0x4000 +#define PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT 0x8000 #define PHP_OUTPUT_HANDLER_ABILITY_FLAGS(bitmask) ((bitmask) & ~0xf00f) diff --git a/main/php_streams.h b/main/php_streams.h index 81fba301c6834..1c52539cfcaee 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -361,7 +361,7 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence); #define php_stream_rewind(stream) _php_stream_seek((stream), 0L, SEEK_SET) #define php_stream_seek(stream, offset, whence) _php_stream_seek((stream), (offset), (whence)) -PHPAPI zend_off_t _php_stream_tell(php_stream *stream); +PHPAPI zend_off_t _php_stream_tell(const php_stream *stream); #define php_stream_tell(stream) _php_stream_tell((stream)) PHPAPI ssize_t _php_stream_read(php_stream *stream, char *buf, size_t count); @@ -531,7 +531,7 @@ PHPAPI zend_result _php_stream_copy_to_stream_ex(php_stream *src, php_stream *de /* read all data from stream and put into a buffer. Caller must free buffer * when done. */ -PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int persistent STREAMS_DC); +PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, bool persistent STREAMS_DC); #define php_stream_copy_to_mem(src, maxlen, persistent) _php_stream_copy_to_mem((src), (maxlen), (persistent) STREAMS_CC) /* output all data from a stream */ @@ -561,7 +561,7 @@ END_EXTERN_C() #define PHP_STREAM_CAST_INTERNAL 0x20000000 /* stream cast for internal use */ #define PHP_STREAM_CAST_MASK (PHP_STREAM_CAST_TRY_HARD | PHP_STREAM_CAST_RELEASE | PHP_STREAM_CAST_INTERNAL) BEGIN_EXTERN_C() -PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err); +PHPAPI zend_result _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err); END_EXTERN_C() /* use this to check if a stream can be cast into another form */ #define php_stream_can_cast(stream, as) _php_stream_cast((stream), (as), NULL, 0) @@ -626,7 +626,7 @@ END_EXTERN_C() /* this flag is only used by include/require functions */ #define STREAM_OPEN_FOR_ZEND_STREAM 0x00010000 -int php_init_stream_wrappers(int module_number); +zend_result php_init_stream_wrappers(int module_number); void php_shutdown_stream_wrappers(int module_number); void php_shutdown_stream_hashes(void); PHP_RSHUTDOWN_FUNCTION(streams); @@ -646,15 +646,18 @@ PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf); /* pushes an error message onto the stack for a wrapper instance */ PHPAPI void php_stream_wrapper_log_error(const php_stream_wrapper *wrapper, int options, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ -#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ -#define PHP_STREAM_FAILED 2 /* an error occurred while attempting conversion */ -#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */ +typedef enum { + PHP_STREAM_UNCHANGED = 0, /* orig stream was seekable anyway */ + PHP_STREAM_RELEASED = 1, /* newstream should be used; origstream is no longer valid */ + PHP_STREAM_FAILED = 2, /* an error occurred while attempting conversion */ + PHP_STREAM_CRITICAL = 3, /* an error occurred; origstream is in an unknown state; you should close origstream */ +} php_stream_make_seekable_status; + #define PHP_STREAM_NO_PREFERENCE 0 #define PHP_STREAM_PREFER_STDIO 1 #define PHP_STREAM_FORCE_CONVERSION 2 /* DO NOT call this on streams that are referenced by resources! */ -PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC); +PHPAPI php_stream_make_seekable_status _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC); #define php_stream_make_seekable(origstream, newstream, flags) _php_stream_make_seekable((origstream), (newstream), (flags) STREAMS_CC) /* Give other modules access to the url_stream_wrappers_hash and stream_filters_hash */ diff --git a/main/php_variables.c b/main/php_variables.c index b81c049f6c5b3..707564e680239 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -346,7 +346,7 @@ static bool add_post_var(zval *arr, post_var_data_t *var, bool eof) size_t new_vlen; if (var->ptr >= var->end) { - return 0; + return false; } start = var->ptr + var->already_scanned; @@ -354,7 +354,7 @@ static bool add_post_var(zval *arr, post_var_data_t *var, bool eof) if (!vsep) { if (!eof) { var->already_scanned = var->end - var->ptr; - return 0; + return false; } else { vsep = var->end; } @@ -387,10 +387,10 @@ static bool add_post_var(zval *arr, post_var_data_t *var, bool eof) var->ptr = vsep + (vsep != var->end); var->already_scanned = 0; - return 1; + return true; } -static inline int add_post_vars(zval *arr, post_var_data_t *vars, bool eof) +static inline zend_result add_post_vars(zval *arr, post_var_data_t *vars, bool eof) { uint64_t max_vars = REQUEST_PARSE_BODY_OPTION_GET(max_input_vars, PG(max_input_vars)); @@ -782,13 +782,16 @@ static void php_autoglobal_merge(HashTable *dest, HashTable *src) /* }}} */ /* {{{ php_hash_environment */ -PHPAPI int php_hash_environment(void) +PHPAPI zend_result php_hash_environment(void) { memset(PG(http_globals), 0, sizeof(PG(http_globals))); + /* Register $argc and $argv for CLI SAPIs. $_SERVER['argc'] and $_SERVER['argv'] + * will be registered in php_auto_globals_create_server() which clears + * PG(http_globals)[TRACK_VARS_SERVER] anyways, making registration at this point + * useless. + */ + php_build_argv(NULL, NULL); zend_activate_auto_globals(); - if (PG(register_argc_argv)) { - php_build_argv(SG(request_info).query_string, &PG(http_globals)[TRACK_VARS_SERVER]); - } return SUCCESS; } /* }}} */ @@ -805,7 +808,7 @@ static bool php_auto_globals_create_get(zend_string *name) zend_hash_update(&EG(symbol_table), name, &PG(http_globals)[TRACK_VARS_GET]); Z_ADDREF(PG(http_globals)[TRACK_VARS_GET]); - return 0; /* don't rearm */ + return false; /* don't rearm */ } static bool php_auto_globals_create_post(zend_string *name) @@ -824,7 +827,7 @@ static bool php_auto_globals_create_post(zend_string *name) zend_hash_update(&EG(symbol_table), name, &PG(http_globals)[TRACK_VARS_POST]); Z_ADDREF(PG(http_globals)[TRACK_VARS_POST]); - return 0; /* don't rearm */ + return false; /* don't rearm */ } static bool php_auto_globals_create_cookie(zend_string *name) @@ -839,7 +842,7 @@ static bool php_auto_globals_create_cookie(zend_string *name) zend_hash_update(&EG(symbol_table), name, &PG(http_globals)[TRACK_VARS_COOKIE]); Z_ADDREF(PG(http_globals)[TRACK_VARS_COOKIE]); - return 0; /* don't rearm */ + return false; /* don't rearm */ } static bool php_auto_globals_create_files(zend_string *name) @@ -851,7 +854,7 @@ static bool php_auto_globals_create_files(zend_string *name) zend_hash_update(&EG(symbol_table), name, &PG(http_globals)[TRACK_VARS_FILES]); Z_ADDREF(PG(http_globals)[TRACK_VARS_FILES]); - return 0; /* don't rearm */ + return false; /* don't rearm */ } /* Ugly hack to fix HTTP_PROXY issue, see bug #72573 */ @@ -875,19 +878,18 @@ static bool php_auto_globals_create_server(zend_string *name) if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) { php_register_server_variables(); - if (PG(register_argc_argv)) { - if (SG(request_info).argc) { - zval *argc, *argv; + if (SG(request_info).argc) { + zval *argc, *argv; - if ((argc = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), 1)) != NULL && - (argv = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL) { - Z_ADDREF_P(argv); - zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGV), argv); - zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGC), argc); - } - } else { - php_build_argv(SG(request_info).query_string, &PG(http_globals)[TRACK_VARS_SERVER]); + if ((argc = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), 1)) != NULL && + (argv = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL) { + Z_ADDREF_P(argv); + zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGV), argv); + zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGC), argc); } + } else if (PG(register_argc_argv)) { + zend_error(E_DEPRECATED, "Deriving $_SERVER['argv'] from the query string is deprecated. Configure register_argc_argv=0 to turn this message off"); + php_build_argv(SG(request_info).query_string, &PG(http_globals)[TRACK_VARS_SERVER]); } } else { @@ -905,7 +907,7 @@ static bool php_auto_globals_create_server(zend_string *name) * ignore this issue, as it would probably require larger changes. */ HT_ALLOW_COW_VIOLATION(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])); - return 0; /* don't rearm */ + return false; /* don't rearm */ } static bool php_auto_globals_create_env(zend_string *name) @@ -921,7 +923,7 @@ static bool php_auto_globals_create_env(zend_string *name) zend_hash_update(&EG(symbol_table), name, &PG(http_globals)[TRACK_VARS_ENV]); Z_ADDREF(PG(http_globals)[TRACK_VARS_ENV]); - return 0; /* don't rearm */ + return false; /* don't rearm */ } static bool php_auto_globals_create_request(zend_string *name) @@ -965,7 +967,7 @@ static bool php_auto_globals_create_request(zend_string *name) } zend_hash_update(&EG(symbol_table), name, &form_variables); - return 0; + return false; } void php_startup_auto_globals(void) diff --git a/main/php_variables.h b/main/php_variables.h index f2b4b8cae241a..5cb43890bd756 100644 --- a/main/php_variables.h +++ b/main/php_variables.h @@ -39,7 +39,7 @@ PHPAPI void php_register_variable_ex(const char *var, zval *val, zval *track_var PHPAPI void php_register_known_variable(const char *var, size_t var_len, zval *value, zval *track_vars_array); PHPAPI void php_build_argv(const char *s, zval *track_vars_array); -PHPAPI int php_hash_environment(void); +PHPAPI zend_result php_hash_environment(void); END_EXTERN_C() #define NUM_TRACK_VARS 6 diff --git a/main/snprintf.c b/main/snprintf.c index de69200304a43..e9938c79659f4 100644 --- a/main/snprintf.c +++ b/main/snprintf.c @@ -613,19 +613,11 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ break; case 'j': fmt++; -#if SIZEOF_INTMAX_T modifier = LM_INTMAX_T; -#else - modifier = LM_SIZE_T; -#endif break; case 't': fmt++; -#if SIZEOF_PTRDIFF_T modifier = LM_PTRDIFF_T; -#else - modifier = LM_SIZE_T; -#endif break; case 'p': { @@ -689,16 +681,12 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ i_num = (int64_t) va_arg(ap, unsigned long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: i_num = (int64_t) va_arg(ap, uintmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: i_num = (int64_t) va_arg(ap, ptrdiff_t); break; -#endif } /* * The rest also applies to other integer formats, so fall @@ -721,27 +709,19 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ i_num = (int64_t) va_arg(ap, long int); break; case LM_SIZE_T: -#if SIZEOF_SSIZE_T i_num = (int64_t) va_arg(ap, ssize_t); -#else - i_num = (int64_t) va_arg(ap, size_t); -#endif break; #if SIZEOF_LONG_LONG case LM_LONG_LONG: i_num = (int64_t) va_arg(ap, long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: i_num = (int64_t) va_arg(ap, intmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: i_num = (int64_t) va_arg(ap, ptrdiff_t); break; -#endif } } s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative, @@ -778,16 +758,12 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ ui_num = (uint64_t) va_arg(ap, unsigned long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: ui_num = (uint64_t) va_arg(ap, uintmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: ui_num = (uint64_t) va_arg(ap, ptrdiff_t); break; -#endif } s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); FIX_PRECISION(adjust_precision, precision, s, s_len); @@ -817,16 +793,12 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ ui_num = (uint64_t) va_arg(ap, unsigned long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: ui_num = (uint64_t) va_arg(ap, uintmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: ui_num = (uint64_t) va_arg(ap, ptrdiff_t); break; -#endif } s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); FIX_PRECISION(adjust_precision, precision, s, s_len); diff --git a/main/snprintf.h b/main/snprintf.h index 2ff7116c3fbb4..d61ee5e39a696 100644 --- a/main/snprintf.h +++ b/main/snprintf.h @@ -113,12 +113,8 @@ END_EXTERN_C() typedef enum { LM_STD = 0, -#if SIZEOF_INTMAX_T LM_INTMAX_T, -#endif -#if SIZEOF_PTRDIFF_T LM_PTRDIFF_T, -#endif #if SIZEOF_LONG_LONG LM_LONG_LONG, #endif diff --git a/main/spprintf.c b/main/spprintf.c index f180ad31b3da9..0dd7f1552e1c8 100644 --- a/main/spprintf.c +++ b/main/spprintf.c @@ -313,19 +313,11 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ break; case 'j': fmt++; -#if SIZEOF_INTMAX_T modifier = LM_INTMAX_T; -#else - modifier = LM_SIZE_T; -#endif break; case 't': fmt++; -#if SIZEOF_PTRDIFF_T modifier = LM_PTRDIFF_T; -#else - modifier = LM_SIZE_T; -#endif break; case 'p': { @@ -398,16 +390,12 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ i_num = (int64_t) va_arg(ap, unsigned long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: i_num = (int64_t) va_arg(ap, uintmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: i_num = (int64_t) va_arg(ap, ptrdiff_t); break; -#endif } /* * The rest also applies to other integer formats, so fall @@ -430,27 +418,19 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ i_num = (int64_t) va_arg(ap, long int); break; case LM_SIZE_T: -#if SIZEOF_SSIZE_T i_num = (int64_t) va_arg(ap, ssize_t); -#else - i_num = (int64_t) va_arg(ap, size_t); -#endif break; #if SIZEOF_LONG_LONG case LM_LONG_LONG: i_num = (int64_t) va_arg(ap, long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: i_num = (int64_t) va_arg(ap, intmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: i_num = (int64_t) va_arg(ap, ptrdiff_t); break; -#endif } } s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative, @@ -486,16 +466,12 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ ui_num = (uint64_t) va_arg(ap, unsigned long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: ui_num = (uint64_t) va_arg(ap, uintmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: ui_num = (uint64_t) va_arg(ap, ptrdiff_t); break; -#endif } s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); @@ -526,16 +502,12 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ ui_num = (uint64_t) va_arg(ap, unsigned long long int); break; #endif -#if SIZEOF_INTMAX_T case LM_INTMAX_T: ui_num = (uint64_t) va_arg(ap, uintmax_t); break; -#endif -#if SIZEOF_PTRDIFF_T case LM_PTRDIFF_T: ui_num = (uint64_t) va_arg(ap, ptrdiff_t); break; -#endif } s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); diff --git a/main/streams/cast.c b/main/streams/cast.c index 6e5c63fb3b292..4b7183024571b 100644 --- a/main/streams/cast.c +++ b/main/streams/cast.c @@ -191,7 +191,7 @@ void php_stream_mode_sanitize_fdopen_fopencookie(php_stream *stream, char *resul /* }}} */ /* {{{ php_stream_cast */ -PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err) +PHPAPI zend_result _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err) { int flags = castas & PHP_STREAM_CAST_MASK; castas &= ~PHP_STREAM_CAST_MASK; @@ -273,12 +273,12 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show newstream = php_stream_fopen_tmpfile(); if (newstream) { - int retcopy = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL, NULL); + zend_result retcopy = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL, NULL); if (retcopy != SUCCESS) { php_stream_close(newstream); } else { - int retcast = php_stream_cast(newstream, castas | flags, (void **)ret, show_err); + zend_result retcast = php_stream_cast(newstream, castas | flags, (void **)ret, show_err); if (retcast == SUCCESS) { rewind(*(FILE**)ret); @@ -370,7 +370,7 @@ PHPAPI FILE * _php_stream_open_wrapper_as_file(char *path, char *mode, int optio /* }}} */ /* {{{ php_stream_make_seekable */ -PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC) +PHPAPI php_stream_make_seekable_status _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC) { if (newstream == NULL) { return PHP_STREAM_FAILED; diff --git a/main/streams/filter.c b/main/streams/filter.c index abfc5c26ae12d..741dcde684d6c 100644 --- a/main/streams/filter.c +++ b/main/streams/filter.c @@ -15,10 +15,8 @@ */ #include "php.h" -#include "php_globals.h" #include "php_network.h" -#include "php_open_temporary_file.h" -#include "ext/standard/file.h" +#include "ext/standard/file.h" /* For FG(stream_filters) */ #include #include @@ -40,22 +38,22 @@ PHPAPI HashTable *_php_get_stream_filters_hash(void) } /* API for registering GLOBAL filters */ -PHPAPI int php_stream_filter_register_factory(const char *filterpattern, const php_stream_filter_factory *factory) +PHPAPI zend_result php_stream_filter_register_factory(const char *filterpattern, const php_stream_filter_factory *factory) { - int ret; - zend_string *str = zend_string_init_interned(filterpattern, strlen(filterpattern), 1); + zend_result ret; + zend_string *str = zend_string_init_interned(filterpattern, strlen(filterpattern), true); ret = zend_hash_add_ptr(&stream_filters_hash, str, (void*)factory) ? SUCCESS : FAILURE; - zend_string_release_ex(str, 1); + zend_string_release_ex(str, true); return ret; } -PHPAPI int php_stream_filter_unregister_factory(const char *filterpattern) +PHPAPI zend_result php_stream_filter_unregister_factory(const char *filterpattern) { return zend_hash_str_del(&stream_filters_hash, filterpattern, strlen(filterpattern)); } /* API for registering VOLATILE wrappers */ -PHPAPI int php_stream_filter_register_factory_volatile(zend_string *filterpattern, const php_stream_filter_factory *factory) +PHPAPI zend_result php_stream_filter_register_factory_volatile(zend_string *filterpattern, const php_stream_filter_factory *factory) { if (!FG(stream_filters)) { ALLOC_HASHTABLE(FG(stream_filters)); @@ -68,9 +66,9 @@ PHPAPI int php_stream_filter_register_factory_volatile(zend_string *filterpatter /* Buckets */ -PHPAPI php_stream_bucket *php_stream_bucket_new(php_stream *stream, char *buf, size_t buflen, uint8_t own_buf, uint8_t buf_persistent) +PHPAPI php_stream_bucket *php_stream_bucket_new(const php_stream *stream, char *buf, size_t buflen, uint8_t own_buf, uint8_t buf_persistent) { - int is_persistent = php_stream_is_persistent(stream); + bool is_persistent = php_stream_is_persistent(stream); php_stream_bucket *bucket; bucket = (php_stream_bucket*)pemalloc(sizeof(php_stream_bucket), is_persistent); @@ -78,10 +76,10 @@ PHPAPI php_stream_bucket *php_stream_bucket_new(php_stream *stream, char *buf, s if (is_persistent && !buf_persistent) { /* all data in a persistent bucket must also be persistent */ - bucket->buf = pemalloc(buflen, 1); + bucket->buf = pemalloc(buflen, true); memcpy(bucket->buf, buf, buflen); bucket->buflen = buflen; - bucket->own_buf = 1; + bucket->own_buf = true; } else { bucket->buf = buf; bucket->buflen = buflen; @@ -118,7 +116,7 @@ PHPAPI php_stream_bucket *php_stream_bucket_make_writeable(php_stream_bucket *bu memcpy(retval->buf, bucket->buf, retval->buflen); retval->refcount = 1; - retval->own_buf = 1; + retval->own_buf = true; php_stream_bucket_delref(bucket); @@ -134,14 +132,14 @@ PHPAPI int php_stream_bucket_split(php_stream_bucket *in, php_stream_bucket **le (*left)->buflen = length; memcpy((*left)->buf, in->buf, length); (*left)->refcount = 1; - (*left)->own_buf = 1; + (*left)->own_buf = true; (*left)->is_persistent = in->is_persistent; (*right)->buflen = in->buflen - length; (*right)->buf = pemalloc((*right)->buflen, in->is_persistent); memcpy((*right)->buf, in->buf + length, (*right)->buflen); (*right)->refcount = 1; - (*right)->own_buf = 1; + (*right)->own_buf = true; (*right)->is_persistent = in->is_persistent; return SUCCESS; @@ -282,7 +280,7 @@ PHPAPI void php_stream_filter_free(php_stream_filter *filter) pefree(filter, filter->is_persistent); } -PHPAPI int php_stream_filter_prepend_ex(php_stream_filter_chain *chain, php_stream_filter *filter) +PHPAPI void php_stream_filter_prepend_ex(php_stream_filter_chain *chain, php_stream_filter *filter) { filter->next = chain->head; filter->prev = NULL; @@ -294,8 +292,6 @@ PHPAPI int php_stream_filter_prepend_ex(php_stream_filter_chain *chain, php_stre } chain->head = filter; filter->chain = chain; - - return SUCCESS; } PHPAPI void _php_stream_filter_prepend(php_stream_filter_chain *chain, php_stream_filter *filter) @@ -303,7 +299,7 @@ PHPAPI void _php_stream_filter_prepend(php_stream_filter_chain *chain, php_strea php_stream_filter_prepend_ex(chain, filter); } -PHPAPI int php_stream_filter_append_ex(php_stream_filter_chain *chain, php_stream_filter *filter) +PHPAPI zend_result php_stream_filter_append_ex(php_stream_filter_chain *chain, php_stream_filter *filter) { php_stream *stream = chain->stream; @@ -354,6 +350,13 @@ PHPAPI int php_stream_filter_append_ex(php_stream_filter_chain *chain, php_strea Reset stream's internal read buffer since the filter is "holding" it. */ stream->readpos = 0; stream->writepos = 0; + + /* Filter could have added buckets anyway, but signalled that it did not return any. Discard them. */ + while (brig_out.head) { + bucket = brig_out.head; + php_stream_bucket_unlink(bucket); + php_stream_bucket_delref(bucket); + } break; case PSFS_PASS_ON: /* If any data is consumed, we cannot rely upon the existing read buffer, @@ -395,7 +398,7 @@ PHPAPI void _php_stream_filter_append(php_stream_filter_chain *chain, php_stream } } -PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish) +PHPAPI zend_result _php_stream_filter_flush(php_stream_filter *filter, bool finish) { php_stream_bucket_brigade brig_a = { NULL, NULL }, brig_b = { NULL, NULL }, *inp = &brig_a, *outp = &brig_b, *brig_temp; php_stream_bucket *bucket; @@ -403,7 +406,7 @@ PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish) php_stream_filter *current; php_stream *stream; size_t flushed_size = 0; - long flags = (finish ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC); + int flags = (finish ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC); if (!filter->chain || !filter->chain->stream) { /* Filter is not attached to a chain, or chain is somehow not part of a stream */ @@ -480,7 +483,7 @@ PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish) return SUCCESS; } -PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor) +PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, bool call_dtor) { if (filter->prev) { filter->prev->next = filter->next; diff --git a/main/streams/php_stream_context.h b/main/streams/php_stream_context.h index a09b61923ade2..cc001cced1541 100644 --- a/main/streams/php_stream_context.h +++ b/main/streams/php_stream_context.h @@ -44,7 +44,7 @@ typedef struct _php_stream_notifier php_stream_notifier; struct _php_stream_notifier { php_stream_notification_func func; void (*dtor)(php_stream_notifier *notifier); - zval ptr; + void *ptr; int mask; size_t progress, progress_max; /* position for progress notification */ }; @@ -59,12 +59,16 @@ BEGIN_EXTERN_C() PHPAPI int php_le_stream_context(void); PHPAPI void php_stream_context_free(php_stream_context *context); PHPAPI php_stream_context *php_stream_context_alloc(void); -PHPAPI zval *php_stream_context_get_option(php_stream_context *context, +PHPAPI zval *php_stream_context_get_option(const php_stream_context *context, const char *wrappername, const char *optionname); PHPAPI void php_stream_context_set_option(php_stream_context *context, const char *wrappername, const char *optionname, zval *optionvalue); void php_stream_context_unset_option(php_stream_context *context, const char *wrappername, const char *optionname); + +struct php_uri_parser; + +PHPAPI const struct php_uri_parser *php_stream_context_get_uri_parser(const char *wrappername, php_stream_context *context); PHPAPI php_stream_notifier *php_stream_notification_alloc(void); PHPAPI void php_stream_notification_free(php_stream_notifier *notifier); END_EXTERN_C() diff --git a/main/streams/php_stream_filter_api.h b/main/streams/php_stream_filter_api.h index ee6ab75f38c23..e224b85b2d9a2 100644 --- a/main/streams/php_stream_filter_api.h +++ b/main/streams/php_stream_filter_api.h @@ -44,8 +44,8 @@ struct _php_stream_bucket { char *buf; size_t buflen; /* if non-zero, buf should be pefreed when the bucket is destroyed */ - uint8_t own_buf; - uint8_t is_persistent; + bool own_buf; + bool is_persistent; /* destroy this struct when refcount falls to zero */ int refcount; @@ -63,7 +63,7 @@ typedef enum { /* Buckets API. */ BEGIN_EXTERN_C() -PHPAPI php_stream_bucket *php_stream_bucket_new(php_stream *stream, char *buf, size_t buflen, uint8_t own_buf, uint8_t buf_persistent); +PHPAPI php_stream_bucket *php_stream_bucket_new(const php_stream *stream, char *buf, size_t buflen, uint8_t own_buf, uint8_t buf_persistent); PHPAPI int php_stream_bucket_split(php_stream_bucket *in, php_stream_bucket **left, php_stream_bucket **right, size_t length); PHPAPI void php_stream_bucket_delref(php_stream_bucket *bucket); #define php_stream_bucket_addref(bucket) (bucket)->refcount++ @@ -121,11 +121,11 @@ struct _php_stream_filter { /* stack filter onto a stream */ BEGIN_EXTERN_C() PHPAPI void _php_stream_filter_prepend(php_stream_filter_chain *chain, php_stream_filter *filter); -PHPAPI int php_stream_filter_prepend_ex(php_stream_filter_chain *chain, php_stream_filter *filter); +PHPAPI void php_stream_filter_prepend_ex(php_stream_filter_chain *chain, php_stream_filter *filter); PHPAPI void _php_stream_filter_append(php_stream_filter_chain *chain, php_stream_filter *filter); -PHPAPI int php_stream_filter_append_ex(php_stream_filter_chain *chain, php_stream_filter *filter); -PHPAPI int _php_stream_filter_flush(php_stream_filter *filter, int finish); -PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor); +PHPAPI zend_result php_stream_filter_append_ex(php_stream_filter_chain *chain, php_stream_filter *filter); +PHPAPI zend_result _php_stream_filter_flush(php_stream_filter *filter, bool finish); +PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, bool call_dtor); PHPAPI void php_stream_filter_free(php_stream_filter *filter); PHPAPI php_stream_filter *_php_stream_filter_alloc(const php_stream_filter_ops *fops, void *abstract, uint8_t persistent STREAMS_DC); END_EXTERN_C() @@ -142,8 +142,8 @@ typedef struct _php_stream_filter_factory { } php_stream_filter_factory; BEGIN_EXTERN_C() -PHPAPI int php_stream_filter_register_factory(const char *filterpattern, const php_stream_filter_factory *factory); -PHPAPI int php_stream_filter_unregister_factory(const char *filterpattern); -PHPAPI int php_stream_filter_register_factory_volatile(zend_string *filterpattern, const php_stream_filter_factory *factory); +PHPAPI zend_result php_stream_filter_register_factory(const char *filterpattern, const php_stream_filter_factory *factory); +PHPAPI zend_result php_stream_filter_unregister_factory(const char *filterpattern); +PHPAPI zend_result php_stream_filter_register_factory_volatile(zend_string *filterpattern, const php_stream_filter_factory *factory); PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval *filterparams, uint8_t persistent); END_EXTERN_C() diff --git a/main/streams/streams.c b/main/streams/streams.c index 2eef790863f61..5db9cf6dadc75 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -28,6 +28,7 @@ #include "ext/standard/file.h" #include "ext/standard/basic_functions.h" /* for BG(CurrentStatFile) */ #include "ext/standard/php_string.h" /* for php_memnstr, used by php_stream_get_record() */ +#include "ext/uri/php_uri.h" #include #include #include "php_streams_int.h" @@ -35,9 +36,9 @@ /* {{{ resource and registration code */ /* Global wrapper hash, copied to FG(stream_wrappers) on registration of volatile wrapper */ static HashTable url_stream_wrappers_hash; -static int le_stream = FAILURE; /* true global */ -static int le_pstream = FAILURE; /* true global */ -static int le_stream_filter = FAILURE; /* true global */ +static int le_stream = -1; /* true global */ +static int le_pstream = -1; /* true global */ +static int le_stream_filter = -1; /* true global */ PHPAPI int php_file_le_stream(void) { @@ -630,6 +631,12 @@ PHPAPI zend_result _php_stream_fill_read_buffer(php_stream *stream, size_t size) /* when a filter needs feeding, there is no brig_out to deal with. * we simply continue the loop; if the caller needs more data, * we will read again, otherwise out job is done here */ + + /* Filter could have added buckets anyway, but signalled that it did not return any. Discard them. */ + while ((bucket = brig_outp->head)) { + php_stream_bucket_unlink(bucket); + php_stream_bucket_delref(bucket); + } break; case PSFS_ERR_FATAL: @@ -880,7 +887,7 @@ PHPAPI int _php_stream_stat(php_stream *stream, php_stream_statbuf *ssb) PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf) { size_t avail; - const char *cr, *lf, *eol = NULL; + const char *eol = NULL; const char *readptr; if (!buf) { @@ -893,8 +900,8 @@ PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf) /* Look for EOL */ if (stream->flags & PHP_STREAM_FLAG_DETECT_EOL) { - cr = memchr(readptr, '\r', avail); - lf = memchr(readptr, '\n', avail); + const char *cr = memchr(readptr, '\r', avail); + const char *lf = memchr(readptr, '\n', avail); if (cr && lf != cr + 1 && !(lf && lf < cr)) { /* mac */ @@ -1041,12 +1048,13 @@ PHPAPI char *_php_stream_get_line(php_stream *stream, char *buf, size_t maxlen, #define STREAM_BUFFERED_AMOUNT(stream) \ ((size_t)(((stream)->writepos) - (stream)->readpos)) -static const char *_php_stream_search_delim(php_stream *stream, - size_t maxlen, - size_t skiplen, - const char *delim, /* non-empty! */ - size_t delim_len) -{ +static const char *_php_stream_search_delim( + const php_stream *stream, + size_t maxlen, + size_t skiplen, + const char *delim, /* non-empty! */ + size_t delim_len +) { size_t seek_len; /* set the maximum number of bytes we're allowed to read from buffer */ @@ -1217,16 +1225,15 @@ static ssize_t _php_stream_write_filtered(php_stream *stream, const char *buf, s size_t consumed = 0; php_stream_bucket *bucket; php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL }; - php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out, *brig_swap; + php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out; php_stream_filter_status_t status = PSFS_ERR_FATAL; - php_stream_filter *filter; if (buf) { bucket = php_stream_bucket_new(stream, (char *)buf, count, 0, 0); php_stream_bucket_append(&brig_in, bucket); } - for (filter = stream->writefilters.head; filter; filter = filter->next) { + for (php_stream_filter *filter = stream->writefilters.head; filter; filter = filter->next) { /* for our return value, we are interested in the number of bytes consumed from * the first filter in the chain */ status = filter->fops->filter(stream, filter, brig_inp, brig_outp, @@ -1238,7 +1245,7 @@ static ssize_t _php_stream_write_filtered(php_stream *stream, const char *buf, s /* brig_out becomes brig_in. * brig_in will always be empty here, as the filter MUST attach any un-consumed buckets * to its own brigade */ - brig_swap = brig_inp; + php_stream_bucket_brigade *brig_swap = brig_inp; brig_inp = brig_outp; brig_outp = brig_swap; memset(brig_outp, 0, sizeof(*brig_outp)); @@ -1263,14 +1270,22 @@ static ssize_t _php_stream_write_filtered(php_stream *stream, const char *buf, s php_stream_bucket_delref(bucket); } break; - case PSFS_FEED_ME: - /* need more data before we can push data through to the stream */ - break; case PSFS_ERR_FATAL: /* some fatal error. Theoretically, the stream is borked, so all * further writes should fail. */ - return (ssize_t) -1; + consumed = (ssize_t) -1; + ZEND_FALLTHROUGH; + + case PSFS_FEED_ME: + /* need more data before we can push data through to the stream */ + /* Filter could have added buckets anyway, but signalled that it did not return any. Discard them. */ + while (brig_inp->head) { + bucket = brig_inp->head; + php_stream_bucket_unlink(bucket); + php_stream_bucket_delref(bucket); + } + break; } return consumed; @@ -1340,7 +1355,7 @@ PHPAPI ssize_t _php_stream_printf(php_stream *stream, const char *fmt, ...) return count; } -PHPAPI zend_off_t _php_stream_tell(php_stream *stream) +PHPAPI zend_off_t _php_stream_tell(const php_stream *stream) { return stream->position; } @@ -1529,13 +1544,11 @@ PHPAPI ssize_t _php_stream_passthru(php_stream * stream STREAMS_DC) } -PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int persistent STREAMS_DC) +PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, bool persistent STREAMS_DC) { ssize_t ret = 0; char *ptr; size_t len = 0, buflen; - int step = CHUNK_SIZE; - int min_room = CHUNK_SIZE / 4; php_stream_statbuf ssbuf; zend_string *result; @@ -1578,20 +1591,21 @@ PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int * we can. Note that the stream may be filtered, in which case the stat * result may be inaccurate, as the filter may inflate or deflate the * number of bytes that we can read. In order to avoid an upsize followed - * by a downsize of the buffer, overestimate by the step size (which is + * by a downsize of the buffer, overestimate by the CHUNK_SIZE size (which is * 8K). */ if (php_stream_stat(src, &ssbuf) == 0 && ssbuf.sb.st_size > 0) { - buflen = MAX(ssbuf.sb.st_size - src->position, 0) + step; + buflen = MAX(ssbuf.sb.st_size - src->position, 0) + CHUNK_SIZE; if (maxlen > 0 && buflen > maxlen) { buflen = maxlen; } } else { - buflen = step; + buflen = CHUNK_SIZE; } result = zend_string_alloc(buflen, persistent); ptr = ZSTR_VAL(result); + const int min_room = CHUNK_SIZE / 4; // TODO: Propagate error? while ((ret = php_stream_read(src, ptr, buflen - len)) > 0) { len += ret; @@ -1599,10 +1613,10 @@ PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int if (maxlen == len) { break; } - if (maxlen > 0 && buflen + step > maxlen) { + if (maxlen > 0 && buflen + CHUNK_SIZE > maxlen) { buflen = maxlen; } else { - buflen += step; + buflen += CHUNK_SIZE; } result = zend_string_extend(result, buflen, persistent); ptr = ZSTR_VAL(result) + len; @@ -1869,7 +1883,7 @@ void php_shutdown_stream_hashes(void) } } -int php_init_stream_wrappers(int module_number) +zend_result php_init_stream_wrappers(int module_number) { le_stream = zend_register_list_destructors_ex(stream_resource_regular_dtor, NULL, "stream", module_number); le_pstream = zend_register_list_destructors_ex(NULL, stream_resource_persistent_dtor, "persistent stream", module_number); @@ -1903,11 +1917,9 @@ void php_shutdown_stream_wrappers(int module_number) /* Validate protocol scheme names during registration * Must conform to /^[a-zA-Z0-9+.-]+$/ */ -static inline zend_result php_stream_wrapper_scheme_validate(const char *protocol, unsigned int protocol_len) +static inline zend_result php_stream_wrapper_scheme_validate(const char *protocol, size_t protocol_len) { - unsigned int i; - - for(i = 0; i < protocol_len; i++) { + for (size_t i = 0; i < protocol_len; i++) { if (!isalnum((int)protocol[i]) && protocol[i] != '+' && protocol[i] != '-' && @@ -1975,7 +1987,7 @@ PHPAPI zend_result php_unregister_url_stream_wrapper_volatile(zend_string *proto /* {{{ php_stream_locate_url_wrapper */ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const char **path_for_open, int options) { - HashTable *wrapper_hash = (FG(stream_wrappers) ? FG(stream_wrappers) : &url_stream_wrappers_hash); + const HashTable *wrapper_hash = (FG(stream_wrappers) ? FG(stream_wrappers) : &url_stream_wrappers_hash); php_stream_wrapper *wrapper = NULL; const char *p, *protocol = NULL; size_t n = 0; @@ -2023,16 +2035,16 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const php_stream_wrapper *plain_files_wrapper = (php_stream_wrapper*)&php_plain_files_wrapper; if (protocol) { - int localhost = 0; + bool localhost = false; if (!strncasecmp(path, "file://localhost/", 17)) { - localhost = 1; + localhost = true; } #ifdef PHP_WIN32 - if (localhost == 0 && path[n+3] != '\0' && path[n+3] != '/' && path[n+4] != ':') { + if (!localhost && path[n+3] != '\0' && path[n+3] != '/' && path[n+4] != ':') { #else - if (localhost == 0 && path[n+3] != '\0' && path[n+3] != '/') { + if (!localhost && path[n+3] != '\0' && path[n+3] != '/') { #endif if (options & REPORT_ERRORS) { php_error_docref(NULL, E_WARNING, "Remote host file access not supported, %s", path); @@ -2043,7 +2055,7 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const if (path_for_open) { /* skip past protocol and :/, but handle windows correctly */ *path_for_open = (char*)path + n + 1; - if (localhost == 1) { + if (localhost) { (*path_for_open) += 11; } while (*(++*path_for_open)=='/') { @@ -2262,7 +2274,7 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod /* if the caller asked for a persistent stream but the wrapper did not * return one, force an error here */ - if (stream && (options & STREAM_OPEN_PERSISTENT) && !stream->is_persistent) { + if (stream && persistent && !stream->is_persistent) { php_stream_wrapper_log_error(wrapper, options & ~REPORT_ERRORS, "wrapper does not support persistent streams"); php_stream_close(stream); @@ -2416,7 +2428,7 @@ PHPAPI void php_stream_notification_free(php_stream_notifier *notifier) efree(notifier); } -PHPAPI zval *php_stream_context_get_option(php_stream_context *context, +PHPAPI zval *php_stream_context_get_option(const php_stream_context *context, const char *wrappername, const char *optionname) { zval *wrapperhash; @@ -2460,6 +2472,24 @@ void php_stream_context_unset_option(php_stream_context *context, } /* }}} */ +PHPAPI const struct php_uri_parser *php_stream_context_get_uri_parser(const char *wrappername, php_stream_context *context) +{ + if (context == NULL) { + return php_uri_get_parser(NULL); + } + + zval *uri_parser_name = php_stream_context_get_option(context, wrappername, "uri_parser_class"); + if (uri_parser_name == NULL || Z_TYPE_P(uri_parser_name) == IS_NULL) { + return php_uri_get_parser(NULL); + } + + if (Z_TYPE_P(uri_parser_name) != IS_STRING) { + return NULL; + } + + return php_uri_get_parser(Z_STR_P(uri_parser_name)); +} + /* {{{ php_stream_dirent_alphasort */ PHPAPI int php_stream_dirent_alphasort(const zend_string **a, const zend_string **b) { diff --git a/main/streams/transports.c b/main/streams/transports.c index 38850a3b541a4..83297d9a06ceb 100644 --- a/main/streams/transports.c +++ b/main/streams/transports.c @@ -130,7 +130,7 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in } stream = (factory)(protocol, n, - (char*)name, namelen, persistent_id, options, flags, timeout, + name, namelen, persistent_id, options, flags, timeout, context STREAMS_REL_CC); if (stream) { diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 0bb80acf6b7c2..888e4c90bbaf9 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -251,13 +251,6 @@ typedef struct _php_userstream_data php_userstream_data_t; }}} **/ -static zend_result call_method_if_exists( - zval *object, zval *method_name, zval *retval, uint32_t param_count, zval *params) -{ - return zend_call_method_if_exists( - Z_OBJ_P(object), Z_STR_P(method_name), retval, param_count, params); -} - static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context, zval *object) { if (uwrap->ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { @@ -295,9 +288,8 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; php_userstream_data_t *us; - zval zretval, zfuncname; + zval zretval; zval args[4]; - int call_result; php_stream *stream = NULL; bool old_in_user_include; @@ -321,33 +313,40 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * us = emalloc(sizeof(*us)); us->wrapper = uwrap; - /* call_method_if_exists() may unregister the stream wrapper. Hold on to it. */ + /* zend_call_method_if_exists() may unregister the stream wrapper. Hold on to it. */ GC_ADDREF(us->wrapper->resource); user_stream_create_object(uwrap, context, &us->object); - if (Z_TYPE(us->object) == IS_UNDEF) { - FG(user_stream_current_filename) = NULL; - PG(in_user_include) = old_in_user_include; - efree(us); - return NULL; + if (Z_ISUNDEF(us->object)) { + goto end; } - /* call it's stream_open method - set up params first */ + /* call its stream_open method - set up params first */ ZVAL_STRING(&args[0], filename); ZVAL_STRING(&args[1], mode); ZVAL_LONG(&args[2], options); ZVAL_NEW_REF(&args[3], &EG(uninitialized_zval)); - ZVAL_STRING(&zfuncname, USERSTREAM_OPEN); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_OPEN, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &zretval, 4, args); + zend_string_release_ex(func_name, false); - zend_try { - call_result = call_method_if_exists(&us->object, &zfuncname, &zretval, 4, args); - } zend_catch { - FG(user_stream_current_filename) = NULL; - zend_bailout(); - } zend_end_try(); + /* Keep arg3 alive if it has assigned the reference */ + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&args[0]); - if (call_result == SUCCESS && Z_TYPE(zretval) != IS_UNDEF && zval_is_true(&zretval)) { + if (UNEXPECTED(call_result == FAILURE)) { + php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_OPEN "\" is not implemented", + ZSTR_VAL(us->wrapper->ce->name)); + zval_ptr_dtor(&args[3]); + goto end; + } + /* Exception occurred */ + if (UNEXPECTED(Z_ISUNDEF(zretval))) { + zval_ptr_dtor(&args[3]); + goto end; + } + if (zval_is_true(&zretval)) { /* the stream is now open! */ stream = php_stream_alloc_rel(&php_stream_userspace_ops, us, 0, mode); @@ -355,6 +354,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * if (Z_ISREF(args[3]) && Z_TYPE_P(Z_REFVAL(args[3])) == IS_STRING && opened_path) { *opened_path = zend_string_copy(Z_STR_P(Z_REFVAL(args[3]))); } + // TODO Warn when assigning a non string value to the reference? /* set wrapper data to be a reference to our object */ ZVAL_COPY(&stream->wrapperdata, &us->object); @@ -363,23 +363,17 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * ZSTR_VAL(us->wrapper->ce->name)); } - /* destroy everything else */ - if (stream == NULL) { - zval_ptr_dtor(&us->object); - ZVAL_UNDEF(&us->object); - zend_list_delete(us->wrapper->resource); - efree(us); - } zval_ptr_dtor(&zretval); - zval_ptr_dtor(&zfuncname); zval_ptr_dtor(&args[3]); - zval_ptr_dtor(&args[2]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); +end: FG(user_stream_current_filename) = NULL; - PG(in_user_include) = old_in_user_include; + if (stream == NULL) { + zval_ptr_dtor(&us->object); + zend_list_delete(us->wrapper->resource); + efree(us); + } return stream; } @@ -396,9 +390,8 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; php_userstream_data_t *us; - zval zretval, zfuncname; + zval zretval; zval args[2]; - int call_result; php_stream *stream = NULL; /* Try to catch bad usage without preventing flexibility */ @@ -410,25 +403,34 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char us = emalloc(sizeof(*us)); us->wrapper = uwrap; - /* call_method_if_exists() may unregister the stream wrapper. Hold on to it. */ + /* zend_call_method_if_exists() may unregister the stream wrapper. Hold on to it. */ GC_ADDREF(us->wrapper->resource); user_stream_create_object(uwrap, context, &us->object); if (Z_TYPE(us->object) == IS_UNDEF) { - FG(user_stream_current_filename) = NULL; - efree(us); - return NULL; + goto end; } - /* call it's dir_open method - set up params first */ + /* call its dir_open method - set up params first */ ZVAL_STRING(&args[0], filename); ZVAL_LONG(&args[1], options); - ZVAL_STRING(&zfuncname, USERSTREAM_DIR_OPEN); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_OPEN, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &zretval, 2, args); + zend_string_release_ex(func_name, false); + zval_ptr_dtor(&args[0]); - call_result = call_method_if_exists(&us->object, &zfuncname, &zretval, 2, args); + if (UNEXPECTED(call_result == FAILURE)) { + php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_DIR_OPEN "\" is not implemented", + ZSTR_VAL(us->wrapper->ce->name)); + goto end; + } + /* Exception occurred in call */ + if (UNEXPECTED(Z_ISUNDEF(zretval))) { + goto end; + } - if (call_result == SUCCESS && Z_TYPE(zretval) != IS_UNDEF && zval_is_true(&zretval)) { + if (zval_is_true(&zretval)) { /* the stream is now open! */ stream = php_stream_alloc_rel(&php_stream_userspace_dir_ops, us, 0, mode); @@ -438,22 +440,15 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char php_stream_wrapper_log_error(wrapper, options, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed", ZSTR_VAL(us->wrapper->ce->name)); } + zval_ptr_dtor(&zretval); - /* destroy everything else */ +end: + FG(user_stream_current_filename) = NULL; if (stream == NULL) { zval_ptr_dtor(&us->object); - ZVAL_UNDEF(&us->object); zend_list_delete(us->wrapper->resource); efree(us); } - zval_ptr_dtor(&zretval); - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - - FG(user_stream_current_filename) = NULL; - return stream; } @@ -562,38 +557,41 @@ PHP_FUNCTION(stream_wrapper_restore) static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_t count) { - zval func_name; zval retval; - int call_result; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; zval args[1]; ssize_t didwrite; assert(us != NULL); - ZVAL_STRINGL(&func_name, USERSTREAM_WRITE, sizeof(USERSTREAM_WRITE)-1); - ZVAL_STRINGL(&args[0], (char*)buf, count); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args); + uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; + + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_WRITE, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, args); + zend_string_release_ex(func_name, false); zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&func_name); - if (EG(exception)) { + if (UNEXPECTED(call_result == FAILURE)) { + php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!", + ZSTR_VAL(us->wrapper->ce->name)); + } + + stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= orig_no_fclose; + + /* Exception occurred */ + if (Z_ISUNDEF(retval)) { return -1; } - if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - if (Z_TYPE(retval) == IS_FALSE) { - didwrite = -1; - } else { - convert_to_long(&retval); - didwrite = Z_LVAL(retval); - } - } else { - php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!", - ZSTR_VAL(us->wrapper->ce->name)); + if (Z_TYPE(retval) == IS_FALSE) { didwrite = -1; + } else { + convert_to_long(&retval); + didwrite = Z_LVAL(retval); } /* don't allow strange buffer overruns due to bogus return */ @@ -611,41 +609,38 @@ static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count) { - zval func_name; zval retval; zval args[1]; - int call_result; size_t didread = 0; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; assert(us != NULL); - ZVAL_STRINGL(&func_name, USERSTREAM_READ, sizeof(USERSTREAM_READ)-1); + uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; ZVAL_LONG(&args[0], count); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_READ, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, args); + zend_string_release_ex(func_name, false); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args); - - zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&func_name); - - if (EG(exception)) { - return -1; + if (UNEXPECTED(Z_ISUNDEF(retval))) { + goto err; } - if (call_result == FAILURE) { + if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " is not implemented!", ZSTR_VAL(us->wrapper->ce->name)); - return -1; + goto err; } if (Z_TYPE(retval) == IS_FALSE) { - return -1; + goto err; } if (!try_convert_to_string(&retval)) { zval_ptr_dtor(&retval); - return -1; + goto err; } didread = Z_STRLEN(retval); @@ -663,44 +658,50 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count /* since the user stream has no way of setting the eof flag directly, we need to ask it if we hit eof */ - ZVAL_STRINGL(&func_name, USERSTREAM_EOF, sizeof(USERSTREAM_EOF)-1); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); - zval_ptr_dtor(&func_name); + func_name = ZSTR_INIT_LITERAL(USERSTREAM_EOF, false); + call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); - if (EG(exception)) { - stream->eof = 1; - return -1; - } - - if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) { - stream->eof = 1; - } else if (call_result == FAILURE) { + if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF", ZSTR_VAL(us->wrapper->ce->name)); - stream->eof = 1; + goto err; + } + if (UNEXPECTED(Z_ISUNDEF(retval))) { + stream->eof = 1; + goto err; } + if (zval_is_true(&retval)) { + stream->eof = 1; + } zval_ptr_dtor(&retval); + stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= orig_no_fclose; + return didread; + +err: + stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= orig_no_fclose; + return -1; } static int php_userstreamop_close(php_stream *stream, int close_handle) { - zval func_name; zval retval; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; assert(us != NULL); - ZVAL_STRINGL(&func_name, USERSTREAM_CLOSE, sizeof(USERSTREAM_CLOSE)-1); - - call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_CLOSE, false); + zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); zval_ptr_dtor(&us->object); ZVAL_UNDEF(&us->object); @@ -712,48 +713,40 @@ static int php_userstreamop_close(php_stream *stream, int close_handle) static int php_userstreamop_flush(php_stream *stream) { - zval func_name; zval retval; - int call_result; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; assert(us != NULL); - ZVAL_STRINGL(&func_name, USERSTREAM_FLUSH, sizeof(USERSTREAM_FLUSH)-1); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_FLUSH, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); - - if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) - call_result = 0; - else - call_result = -1; + int ret = call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval) ? 0 : -1; zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); - return call_result; + return ret; } static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) { - zval func_name; zval retval; - int call_result, ret; + int ret; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; zval args[2]; assert(us != NULL); - ZVAL_STRINGL(&func_name, USERSTREAM_SEEK, sizeof(USERSTREAM_SEEK)-1); - ZVAL_LONG(&args[0], offset); ZVAL_LONG(&args[1], whence); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 2, args); + uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; - zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&func_name); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_SEEK, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 2, args); + zend_string_release_ex(func_name, false); if (call_result == FAILURE) { /* stream_seek is not implemented, so disable seeks for this stream */ @@ -762,7 +755,8 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when zval_ptr_dtor(&retval); - return -1; + ret = -1; + goto out; } else if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) { ret = 0; } else { @@ -773,18 +767,18 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when ZVAL_UNDEF(&retval); if (ret) { - return ret; + goto out; } /* now determine where we are */ - ZVAL_STRINGL(&func_name, USERSTREAM_TELL, sizeof(USERSTREAM_TELL)-1); - - call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); + func_name = ZSTR_INIT_LITERAL(USERSTREAM_TELL, false); + call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); if (call_result == SUCCESS && Z_TYPE(retval) == IS_LONG) { *newoffs = Z_LVAL(retval); ret = 0; - } else if (call_result == FAILURE) { + } else if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", ZSTR_VAL(us->wrapper->ce->name)); ret = -1; } else { @@ -792,18 +786,22 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when } zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); + +out: + stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= orig_no_fclose; + return ret; } /* parse the return value from one of the stat functions and store the * relevant fields into the statbuf provided */ -static void statbuf_from_array(zval *array, php_stream_statbuf *ssb) +static void statbuf_from_array(const HashTable *array, php_stream_statbuf *ssb) { zval *elem; #define STAT_PROP_ENTRY_EX(name, name2) \ - if (NULL != (elem = zend_hash_str_find(Z_ARRVAL_P(array), #name, sizeof(#name)-1))) { \ + if (NULL != (elem = zend_hash_str_find(array, #name, sizeof(#name)-1))) { \ ssb->sb.st_##name2 = zval_get_long(elem); \ } @@ -836,205 +834,240 @@ static void statbuf_from_array(zval *array, php_stream_statbuf *ssb) static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb) { - zval func_name; zval retval; - int call_result; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; int ret = -1; - ZVAL_STRINGL(&func_name, USERSTREAM_STAT, sizeof(USERSTREAM_STAT)-1); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_STAT, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); + if (UNEXPECTED(call_result == FAILURE)) { + php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!", + ZSTR_VAL(us->wrapper->ce->name)); + return -1; + } + if (UNEXPECTED(Z_ISUNDEF(retval))) { + return -1; + } - if (call_result == SUCCESS && Z_TYPE(retval) == IS_ARRAY) { - statbuf_from_array(&retval, ssb); + if (EXPECTED(Z_TYPE(retval) == IS_ARRAY)) { + statbuf_from_array(Z_ARR(retval), ssb); ret = 0; - } else { - if (call_result == FAILURE) { - php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!", - ZSTR_VAL(us->wrapper->ce->name)); - } } + // TODO: Warning on incorrect return type? zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); return ret; } - -static int php_userstreamop_set_option(php_stream *stream, int option, int value, void *ptrparam) { - zval func_name; +static int user_stream_set_check_liveliness(const php_userstream_data_t *us) +{ zval retval; - int call_result; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - int ret = PHP_STREAM_OPTION_RETURN_NOTIMPL; - zval args[3]; - switch (option) { - case PHP_STREAM_OPTION_CHECK_LIVENESS: - ZVAL_STRINGL(&func_name, USERSTREAM_EOF, sizeof(USERSTREAM_EOF)-1); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); - if (call_result == SUCCESS && (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) { - ret = zval_is_true(&retval) ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; - } else { - ret = PHP_STREAM_OPTION_RETURN_ERR; - php_error_docref(NULL, E_WARNING, - "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF", - ZSTR_VAL(us->wrapper->ce->name)); - } + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_EOF, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); + + if (UNEXPECTED(call_result == FAILURE)) { + php_error_docref(NULL, E_WARNING, + "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF", + ZSTR_VAL(us->wrapper->ce->name)); + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (UNEXPECTED(Z_ISUNDEF(retval))) { + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (EXPECTED(Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) { + return Z_TYPE(retval) == IS_TRUE ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; + } else { + php_error_docref(NULL, E_WARNING, + "%s::" USERSTREAM_EOF " value must be of type bool, %s given", + ZSTR_VAL(us->wrapper->ce->name), zend_zval_value_name(&retval)); zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); - break; + return PHP_STREAM_OPTION_RETURN_ERR; + } +} - case PHP_STREAM_OPTION_LOCKING: - ZVAL_LONG(&args[0], 0); +static int user_stream_set_locking(const php_userstream_data_t *us, int value) +{ + zval retval; + zval zlock; + zend_long lock = 0; - if (value & LOCK_NB) { - Z_LVAL_P(&args[0]) |= PHP_LOCK_NB; - } - switch(value & ~LOCK_NB) { + if (value & LOCK_NB) { + lock |= PHP_LOCK_NB; + } + switch (value & ~LOCK_NB) { case LOCK_SH: - Z_LVAL_P(&args[0]) |= PHP_LOCK_SH; + lock |= PHP_LOCK_SH; break; case LOCK_EX: - Z_LVAL_P(&args[0]) |= PHP_LOCK_EX; + lock |= PHP_LOCK_EX; break; case LOCK_UN: - Z_LVAL_P(&args[0]) |= PHP_LOCK_UN; + lock |= PHP_LOCK_UN; break; - } - - /* TODO wouldblock */ - ZVAL_STRINGL(&func_name, USERSTREAM_LOCK, sizeof(USERSTREAM_LOCK)-1); - - call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args); - - if (call_result == SUCCESS && (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) { - ret = (Z_TYPE(retval) == IS_FALSE); - } else if (call_result == FAILURE) { - if (value == 0) { - /* lock support test (TODO: more check) */ - ret = PHP_STREAM_OPTION_RETURN_OK; - } else { - php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!", - ZSTR_VAL(us->wrapper->ce->name)); - ret = PHP_STREAM_OPTION_RETURN_ERR; - } - } - - zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); - zval_ptr_dtor(&args[0]); - break; + default: + // TODO: Warn on invalid option value? + ; + } + ZVAL_LONG(&zlock, lock); - case PHP_STREAM_OPTION_TRUNCATE_API: - ZVAL_STRINGL(&func_name, USERSTREAM_TRUNCATE, sizeof(USERSTREAM_TRUNCATE)-1); + /* TODO wouldblock */ + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_LOCK, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, &zlock); + zend_string_release_ex(func_name, false); - switch (value) { - case PHP_STREAM_TRUNCATE_SUPPORTED: - if (zend_is_callable_ex(&func_name, Z_OBJ(us->object), IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, NULL, NULL)) - ret = PHP_STREAM_OPTION_RETURN_OK; - else - ret = PHP_STREAM_OPTION_RETURN_ERR; - break; - - case PHP_STREAM_TRUNCATE_SET_SIZE: { - ptrdiff_t new_size = *(ptrdiff_t*) ptrparam; - if (new_size >= 0 && new_size <= (ptrdiff_t)LONG_MAX) { - ZVAL_LONG(&args[0], (zend_long)new_size); - call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args); - if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) { - if (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE) { - ret = (Z_TYPE(retval) == IS_TRUE) ? PHP_STREAM_OPTION_RETURN_OK : - PHP_STREAM_OPTION_RETURN_ERR; - } else { - php_error_docref(NULL, E_WARNING, - "%s::" USERSTREAM_TRUNCATE " did not return a boolean!", - ZSTR_VAL(us->wrapper->ce->name)); - } - } else { - php_error_docref(NULL, E_WARNING, - "%s::" USERSTREAM_TRUNCATE " is not implemented!", - ZSTR_VAL(us->wrapper->ce->name)); - } - zval_ptr_dtor(&retval); - zval_ptr_dtor(&args[0]); - } else { /* bad new size */ - ret = PHP_STREAM_OPTION_RETURN_ERR; - } - break; - } + if (UNEXPECTED(call_result == FAILURE)) { + if (value == 0) { + /* lock support test (TODO: more check) */ + return PHP_STREAM_OPTION_RETURN_OK; } - zval_ptr_dtor(&func_name); - break; + php_error_docref(NULL, E_WARNING, + "%s::" USERSTREAM_LOCK " is not implemented!", + ZSTR_VAL(us->wrapper->ce->name)); + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (UNEXPECTED(Z_ISUNDEF(retval))) { + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (EXPECTED(Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) { + // This is somewhat confusing and relies on magic numbers. + return Z_TYPE(retval) == IS_FALSE; + } + // TODO: ext/standard/tests/file/userstreams_004.phpt returns null implicitly for function + // Should this warn or not? And should this be considered an error? + //php_error_docref(NULL, E_WARNING, + // "%s::" USERSTREAM_LOCK " value must be of type bool, %s given", + // ZSTR_VAL(us->wrapper->ce->name), zend_zval_value_name(&retval)); + zval_ptr_dtor(&retval); + return PHP_STREAM_OPTION_RETURN_NOTIMPL; +} - case PHP_STREAM_OPTION_READ_BUFFER: - case PHP_STREAM_OPTION_WRITE_BUFFER: - case PHP_STREAM_OPTION_READ_TIMEOUT: - case PHP_STREAM_OPTION_BLOCKING: { +static int user_stream_set_truncation(const php_userstream_data_t *us, int value, void *ptrparam) { + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_TRUNCATE, false); - ZVAL_STRINGL(&func_name, USERSTREAM_SET_OPTION, sizeof(USERSTREAM_SET_OPTION)-1); + if (value == PHP_STREAM_TRUNCATE_SUPPORTED) { + zval zstr; + ZVAL_STR(&zstr, func_name); + bool is_callable = zend_is_callable_ex(&zstr, Z_OBJ(us->object), IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, NULL, NULL); + // Frees func_name + zval_ptr_dtor(&zstr); + return is_callable ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; + } + ZEND_ASSERT(value == PHP_STREAM_TRUNCATE_SET_SIZE); + ptrdiff_t new_size = *(ptrdiff_t*) ptrparam; - ZVAL_LONG(&args[0], option); - ZVAL_NULL(&args[1]); - ZVAL_NULL(&args[2]); + if (UNEXPECTED(new_size < 0 || new_size > (ptrdiff_t)LONG_MAX)) { + /* bad new size */ + zend_string_release_ex(func_name, false); + return PHP_STREAM_OPTION_RETURN_ERR; + } - switch(option) { - case PHP_STREAM_OPTION_READ_BUFFER: - case PHP_STREAM_OPTION_WRITE_BUFFER: - ZVAL_LONG(&args[1], value); - if (ptrparam) { - ZVAL_LONG(&args[2], *(long *)ptrparam); - } else { - ZVAL_LONG(&args[2], BUFSIZ); - } - break; - case PHP_STREAM_OPTION_READ_TIMEOUT: { - struct timeval tv = *(struct timeval*)ptrparam; - ZVAL_LONG(&args[1], tv.tv_sec); - ZVAL_LONG(&args[2], tv.tv_usec); - break; - } - case PHP_STREAM_OPTION_BLOCKING: - ZVAL_LONG(&args[1], value); - break; - default: - break; - } + zval retval; + zval size; - call_result = call_method_if_exists(&us->object, &func_name, &retval, 3, args); + ZVAL_LONG(&size, (zend_long)new_size); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, &size); + zend_string_release_ex(func_name, false); - if (call_result == FAILURE) { - php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!", - ZSTR_VAL(us->wrapper->ce->name)); - ret = PHP_STREAM_OPTION_RETURN_ERR; - } else if (zend_is_true(&retval)) { - ret = PHP_STREAM_OPTION_RETURN_OK; + if (UNEXPECTED(call_result == FAILURE)) { + php_error_docref(NULL, E_WARNING, + "%s::" USERSTREAM_TRUNCATE " is not implemented!", + ZSTR_VAL(us->wrapper->ce->name)); + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (UNEXPECTED(Z_ISUNDEF(retval))) { + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (EXPECTED(Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) { + return Z_TYPE(retval) == IS_TRUE ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; + } else { + php_error_docref(NULL, E_WARNING, + "%s::" USERSTREAM_TRUNCATE " value must be of type bool, %s given", + ZSTR_VAL(us->wrapper->ce->name), zend_zval_value_name(&retval)); + zval_ptr_dtor(&retval); + return PHP_STREAM_OPTION_RETURN_ERR; + } +} + +static int user_stream_set_option(const php_userstream_data_t *us, int option, int value, void *ptrparam) +{ + zval args[3]; + ZVAL_LONG(&args[0], option); + ZVAL_LONG(&args[1], value); + ZVAL_NULL(&args[2]); + + if (option == PHP_STREAM_OPTION_READ_TIMEOUT) { + struct timeval tv = *(struct timeval*)ptrparam; + ZVAL_LONG(&args[1], tv.tv_sec); + ZVAL_LONG(&args[2], tv.tv_usec); + } else if (option == PHP_STREAM_OPTION_READ_BUFFER || option == PHP_STREAM_OPTION_WRITE_BUFFER) { + if (ptrparam) { + ZVAL_LONG(&args[2], *(long *)ptrparam); } else { - ret = PHP_STREAM_OPTION_RETURN_ERR; + ZVAL_LONG(&args[2], BUFSIZ); } + } - zval_ptr_dtor(&retval); - zval_ptr_dtor(&args[2]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&func_name); + zval retval; + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_SET_OPTION, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 3, args); + zend_string_release_ex(func_name, false); - break; - } + if (UNEXPECTED(call_result == FAILURE)) { + php_error_docref(NULL, E_WARNING, + "%s::" USERSTREAM_SET_OPTION " is not implemented!", + ZSTR_VAL(us->wrapper->ce->name)); + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (UNEXPECTED(Z_ISUNDEF(retval))) { + return PHP_STREAM_OPTION_RETURN_ERR; } + int ret; + if (zend_is_true(&retval)) { + ret = PHP_STREAM_OPTION_RETURN_OK; + } else { + ret = PHP_STREAM_OPTION_RETURN_ERR; + } + + zval_ptr_dtor(&retval); return ret; } +static int php_userstreamop_set_option(php_stream *stream, int option, int value, void *ptrparam) { + php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; + + switch (option) { + case PHP_STREAM_OPTION_CHECK_LIVENESS: + return user_stream_set_check_liveliness(us); + + case PHP_STREAM_OPTION_LOCKING: + return user_stream_set_locking(us, value); + + case PHP_STREAM_OPTION_TRUNCATE_API: + return user_stream_set_truncation(us, value, ptrparam); + + case PHP_STREAM_OPTION_READ_BUFFER: + case PHP_STREAM_OPTION_WRITE_BUFFER: + case PHP_STREAM_OPTION_READ_TIMEOUT: + case PHP_STREAM_OPTION_BLOCKING: + return user_stream_set_option(us, option, value, ptrparam); + + default: + return PHP_STREAM_OPTION_RETURN_NOTIMPL; + } +} + static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval zfuncname, zretval; + zval zretval; zval args[1]; - int call_result; zval object; int ret = 0; @@ -1047,22 +1080,21 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int /* call the unlink method */ ZVAL_STRING(&args[0], url); - ZVAL_STRING(&zfuncname, USERSTREAM_UNLINK); - call_result = call_method_if_exists(&object, &zfuncname, &zretval, 1, args); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_UNLINK, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 1, args); + zend_string_release_ex(func_name, false); + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&object); - if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) { - ret = (Z_TYPE(zretval) == IS_TRUE); - } else if (call_result == FAILURE) { + if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", ZSTR_VAL(uwrap->ce->name)); + } else if (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE) { + ret = Z_TYPE(zretval) == IS_TRUE; } + // TODO: Warn on invalid return type, or use zval_is_true()? - /* clean up */ - zval_ptr_dtor(&object); zval_ptr_dtor(&zretval); - zval_ptr_dtor(&zfuncname); - - zval_ptr_dtor(&args[0]); return ret; } @@ -1071,9 +1103,8 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from int options, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval zfuncname, zretval; + zval zretval; zval args[2]; - int call_result; zval object; int ret = 0; @@ -1087,24 +1118,22 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from ZVAL_STRING(&args[0], url_from); ZVAL_STRING(&args[1], url_to); - ZVAL_STRING(&zfuncname, USERSTREAM_RENAME); - - call_result = call_method_if_exists(&object, &zfuncname, &zretval, 2, args); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_RENAME, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 2, args); + zend_string_release_ex(func_name, false); + zval_ptr_dtor(&args[1]); + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&object); - if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) { - ret = (Z_TYPE(zretval) == IS_TRUE); - } else if (call_result == FAILURE) { + if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", ZSTR_VAL(uwrap->ce->name)); + } else if (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE) { + ret = Z_TYPE(zretval) == IS_TRUE; } + // TODO: Warn on invalid return type, or use zval_is_true()? - /* clean up */ - zval_ptr_dtor(&object); zval_ptr_dtor(&zretval); - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - return ret; } @@ -1112,9 +1141,8 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int int options, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval zfuncname, zretval; + zval zretval; zval args[3]; - int call_result; zval object; int ret = 0; @@ -1129,25 +1157,21 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int ZVAL_LONG(&args[1], mode); ZVAL_LONG(&args[2], options); - ZVAL_STRING(&zfuncname, USERSTREAM_MKDIR); - - call_result = call_method_if_exists(&object, &zfuncname, &zretval, 3, args); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_MKDIR, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 3, args); + zend_string_release_ex(func_name, false); + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&object); - if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) { - ret = (Z_TYPE(zretval) == IS_TRUE); - } else if (call_result == FAILURE) { + if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name)); + } else if (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE) { + ret = Z_TYPE(zretval) == IS_TRUE; } + // TODO: Warn on invalid return type, or use zval_is_true()? - /* clean up */ - zval_ptr_dtor(&object); zval_ptr_dtor(&zretval); - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&args[2]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - return ret; } @@ -1155,9 +1179,8 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval zfuncname, zretval; + zval zretval; zval args[2]; - int call_result; zval object; int ret = 0; @@ -1171,24 +1194,21 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, ZVAL_STRING(&args[0], url); ZVAL_LONG(&args[1], options); - ZVAL_STRING(&zfuncname, USERSTREAM_RMDIR); - - call_result = call_method_if_exists(&object, &zfuncname, &zretval, 2, args); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_RMDIR, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 2, args); + zend_string_release_ex(func_name, false); + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&object); - if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) { - ret = (Z_TYPE(zretval) == IS_TRUE); - } else if (call_result == FAILURE) { + if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name)); + } else if (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE) { + ret = Z_TYPE(zretval) == IS_TRUE; } + // TODO: Warn on invalid return type, or use zval_is_true()? - /* clean up */ - zval_ptr_dtor(&object); zval_ptr_dtor(&zretval); - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - return ret; } @@ -1196,9 +1216,8 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i void *value, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval zfuncname, zretval; + zval zretval; zval args[3]; - int call_result; zval object; int ret = 0; @@ -1222,7 +1241,6 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i break; default: php_error_docref(NULL, E_WARNING, "Unknown option %d for " USERSTREAM_METADATA, option); - zval_ptr_dtor(&args[2]); return ret; } @@ -1237,25 +1255,22 @@ static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, i ZVAL_STRING(&args[0], url); ZVAL_LONG(&args[1], option); - ZVAL_STRING(&zfuncname, USERSTREAM_METADATA); - - call_result = call_method_if_exists(&object, &zfuncname, &zretval, 3, args); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_METADATA, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 3, args); + zend_string_release_ex(func_name, false); + zval_ptr_dtor(&args[2]); + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&object); - if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) { - ret = Z_TYPE(zretval) == IS_TRUE; - } else if (call_result == FAILURE) { + if (UNEXPECTED(call_result == FAILURE)) { php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", ZSTR_VAL(uwrap->ce->name)); + } else if (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE) { + ret = Z_TYPE(zretval) == IS_TRUE; } + // TODO: Warn on invalid return type, or use zval_is_true()? - /* clean up */ - zval_ptr_dtor(&object); zval_ptr_dtor(&zretval); - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&args[0]); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[2]); - return ret; } @@ -1264,100 +1279,102 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, i php_stream_statbuf *ssb, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval zfuncname, zretval; + zval zretval; zval args[2]; - int call_result; zval object; int ret = -1; /* create an instance of our class */ user_stream_create_object(uwrap, context, &object); if (Z_TYPE(object) == IS_UNDEF) { - return ret; + return -1; } /* call it's stat_url method - set up params first */ ZVAL_STRING(&args[0], url); ZVAL_LONG(&args[1], flags); - ZVAL_STRING(&zfuncname, USERSTREAM_STATURL); - - call_result = call_method_if_exists(&object, &zfuncname, &zretval, 2, args); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_STATURL, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(object), func_name, &zretval, 2, args); + zend_string_release_ex(func_name, false); + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&object); - if (call_result == SUCCESS && Z_TYPE(zretval) == IS_ARRAY) { - /* We got the info we needed */ - statbuf_from_array(&zretval, ssb); + if (UNEXPECTED(call_result == FAILURE)) { + php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!", + ZSTR_VAL(uwrap->ce->name)); + return -1; + } + if (UNEXPECTED(Z_ISUNDEF(zretval))) { + return -1; + } + if (EXPECTED(Z_TYPE(zretval) == IS_ARRAY)) { + statbuf_from_array(Z_ARR(zretval), ssb); ret = 0; - } else { - if (call_result == FAILURE) { - php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!", - ZSTR_VAL(uwrap->ce->name)); - } } + // TODO: Warning on incorrect return type? - /* clean up */ - zval_ptr_dtor(&object); zval_ptr_dtor(&zretval); - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&args[1]); - zval_ptr_dtor(&args[0]); - return ret; } static ssize_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t count) { - zval func_name; zval retval; - int call_result; size_t didread = 0; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; php_stream_dirent *ent = (php_stream_dirent*)buf; /* avoid problems if someone mis-uses the stream */ - if (count != sizeof(php_stream_dirent)) + if (count != sizeof(php_stream_dirent)) { return -1; + } - ZVAL_STRINGL(&func_name, USERSTREAM_DIR_READ, sizeof(USERSTREAM_DIR_READ)-1); - - call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_READ, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); - if (call_result == SUCCESS && Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) { - convert_to_string(&retval); + if (UNEXPECTED(call_result == FAILURE)) { + php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!", + ZSTR_VAL(us->wrapper->ce->name)); + return -1; + } + if (UNEXPECTED(Z_ISUNDEF(retval))) { + return -1; + } + // TODO: Warn/TypeError for invalid returns? + if (Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) { + if (UNEXPECTED(!try_convert_to_string(&retval))) { + zval_ptr_dtor(&retval); + return -1; + } PHP_STRLCPY(ent->d_name, Z_STRVAL(retval), sizeof(ent->d_name), Z_STRLEN(retval)); ent->d_type = DT_UNKNOWN; didread = sizeof(php_stream_dirent); - } else if (call_result == FAILURE) { - php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!", - ZSTR_VAL(us->wrapper->ce->name)); } zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); return didread; } static int php_userstreamop_closedir(php_stream *stream, int close_handle) { - zval func_name; zval retval; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; assert(us != NULL); - ZVAL_STRINGL(&func_name, USERSTREAM_DIR_CLOSE, sizeof(USERSTREAM_DIR_CLOSE)-1); - - call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_CLOSE, false); + zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); zval_ptr_dtor(&us->object); ZVAL_UNDEF(&us->object); - efree(us); return 0; @@ -1365,16 +1382,14 @@ static int php_userstreamop_closedir(php_stream *stream, int close_handle) static int php_userstreamop_rewinddir(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) { - zval func_name; zval retval; php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - ZVAL_STRINGL(&func_name, USERSTREAM_DIR_REWIND, sizeof(USERSTREAM_DIR_REWIND)-1); - - call_method_if_exists(&us->object, &func_name, &retval, 0, NULL); + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_DIR_REWIND, false); + zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 0, NULL); + zend_string_release_ex(func_name, false); zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); return 0; @@ -1383,17 +1398,13 @@ static int php_userstreamop_rewinddir(php_stream *stream, zend_off_t offset, int static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr) { php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - zval func_name; zval retval; zval args[1]; php_stream * intstream = NULL; - int call_result; int ret = FAILURE; /* If we are checking if the stream can cast, no return pointer is provided, so do not emit errors */ bool report_errors = retptr; - ZVAL_STRINGL(&func_name, USERSTREAM_CAST, sizeof(USERSTREAM_CAST)-1); - switch(castas) { case PHP_STREAM_AS_FD_FOR_SELECT: ZVAL_LONG(&args[0], PHP_STREAM_AS_FD_FOR_SELECT); @@ -1403,19 +1414,26 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr) break; } - call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args); + uint32_t orig_no_fclose = stream->flags & PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE; - do { - if (call_result == FAILURE) { - if (report_errors) { - php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!", - ZSTR_VAL(us->wrapper->ce->name)); - } - break; + zend_string *func_name = ZSTR_INIT_LITERAL(USERSTREAM_CAST, false); + zend_result call_result = zend_call_method_if_exists(Z_OBJ(us->object), func_name, &retval, 1, args); + zend_string_release_ex(func_name, false); + + if (UNEXPECTED(call_result == FAILURE)) { + if (report_errors) { + php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!", + ZSTR_VAL(us->wrapper->ce->name)); } + goto out; + } + + do { if (!zend_is_true(&retval)) { break; } + // TODO: Can this emit an exception even with no error reporting? php_stream_from_zval_no_verify(intstream, &retval); if (!intstream) { if (report_errors) { @@ -1436,8 +1454,10 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr) } while (0); zval_ptr_dtor(&retval); - zval_ptr_dtor(&func_name); - zval_ptr_dtor(&args[0]); + +out: + stream->flags &= ~PHP_STREAM_FLAG_NO_FCLOSE; + stream->flags |= orig_no_fclose; return ret; } diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 3d035de6edb21..ae8cf24c39221 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -80,13 +80,13 @@ static ssize_t php_sockop_write(php_stream *stream, const char *buf, size_t coun if (sock->is_blocked) { int retval; - sock->timeout_event = 0; + sock->timeout_event = false; do { retval = php_pollfd_for(sock->socket, POLLOUT, ptimeout); if (retval == 0) { - sock->timeout_event = 1; + sock->timeout_event = true; break; } @@ -107,8 +107,8 @@ static ssize_t php_sockop_write(php_stream *stream, const char *buf, size_t coun if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) { estr = php_socket_strerror(err, NULL, 0); php_error_docref(NULL, E_NOTICE, - "Send of " ZEND_LONG_FMT " bytes failed with errno=%d %s", - (zend_long)count, err, estr); + "Send of %zu bytes failed with errno=%d %s", + count, err, estr); efree(estr); } } @@ -129,7 +129,7 @@ static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data return; } - sock->timeout_event = 0; + sock->timeout_event = false; if (has_buffered_data) { /* If there is already buffered data, use no timeout. */ @@ -146,7 +146,7 @@ static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data retval = php_pollfd_for(sock->socket, PHP_POLLREADABLE, ptimeout); if (retval == 0) - sock->timeout_event = 1; + sock->timeout_event = true; if (retval >= 0) break; @@ -399,7 +399,7 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void case PHP_STREAM_OPTION_READ_TIMEOUT: sock->timeout = *(struct timeval*)ptrparam; - sock->timeout_event = 0; + sock->timeout_event = false; return PHP_STREAM_OPTION_RETURN_OK; case PHP_STREAM_OPTION_META_DATA_API: @@ -620,12 +620,15 @@ static inline char *parse_ip_address_ex(const char *str, size_t str_len, int *po char *colon; char *host = NULL; -#ifdef HAVE_IPV6 - char *p; + if (memchr(str, '\0', str_len)) { + *err = ZSTR_INIT_LITERAL("The hostname must not contain null bytes", 0); + return NULL; + } +#ifdef HAVE_IPV6 if (*(str) == '[' && str_len > 1) { /* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */ - p = memchr(str + 1, ']', str_len - 2); + char *p = memchr(str + 1, ']', str_len - 2); if (!p || *(p + 1) != ':') { if (get_err) { *err = strpprintf(0, "Failed to parse IPv6 address \"%s\"", str); @@ -854,7 +857,6 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t *sock, php_stream_xport_param *xparam STREAMS_DC) { - int clisock; bool nodelay = 0; zval *tmpzval = NULL; @@ -866,7 +868,7 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t nodelay = 1; } - clisock = php_network_accept_incoming(sock->socket, + php_socket_t clisock = php_network_accept_incoming(sock->socket, xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, xparam->want_addr ? &xparam->outputs.addr : NULL, xparam->want_addr ? &xparam->outputs.addrlen : NULL, @@ -882,7 +884,7 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t clisockdata->socket = clisock; #ifdef __linux__ /* O_NONBLOCK is not inherited on Linux */ - clisockdata->is_blocked = 1; + clisockdata->is_blocked = true; #endif xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+"); @@ -960,7 +962,7 @@ PHPAPI php_stream *php_stream_generic_socket_factory(const char *proto, size_t p sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0); memset(sock, 0, sizeof(php_netstream_data_t)); - sock->is_blocked = 1; + sock->is_blocked = true; sock->timeout.tv_sec = FG(default_socket_timeout); sock->timeout.tv_usec = 0; diff --git a/php.ini-development b/php.ini-development index 162fb3f25c19c..7018682fb0d9a 100644 --- a/php.ini-development +++ b/php.ini-development @@ -129,11 +129,6 @@ ; Development Value: 4096 ; Production Value: 4096 -; register_argc_argv -; Default Value: On -; Development Value: Off -; Production Value: Off - ; request_order ; Default Value: None ; Development Value: "GP" @@ -327,11 +322,6 @@ serialize_precision = -1 ; https://php.net/disable-functions disable_functions = -; This directive allows you to disable certain classes. -; It receives a comma-delimited list of class names. -; https://php.net/disable-classes -disable_classes = - ; Colors for Syntax Highlighting mode. Anything that's acceptable in ; would work. ; https://php.net/syntax-highlighting @@ -436,6 +426,7 @@ max_input_time = 60 ; Maximum amount of memory a script may consume ; https://php.net/memory-limit memory_limit = 128M +max_memory_limit = -1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Error handling and logging ; @@ -536,12 +527,6 @@ ignore_repeated_errors = Off ; https://php.net/ignore-repeated-source ignore_repeated_source = Off -; If this parameter is set to Off, then memory leaks will not be shown (on -; stdout or in the log). This is only effective in a debug compile, and if -; error reporting includes E_WARNING in the allowed list -; https://php.net/report-memleaks -report_memleaks = On - ; This setting is off by default. ;report_zend_debug = 0 @@ -620,6 +605,12 @@ report_memleaks = On ; Development value: 0 ; Production value: 0 +; This directive controls whether PHP will output the backtrace of fatal errors. +; Default Value: On +; Development Value: On +; Production Value: On +;fatal_error_backtraces = On + ;;;;;;;;;;;;;;;;; ; Data Handling ; ;;;;;;;;;;;;;;;;; @@ -669,14 +660,12 @@ request_order = "GP" ; that were passed when the script was invoked. These arrays are extremely ; useful when running scripts from the command line. When this directive is ; enabled, registering these variables consumes CPU cycles and memory each time -; a script is executed. For performance reasons, this feature should be disabled -; on production servers. -; Note: This directive is hardcoded to On for the CLI SAPI -; Default Value: On -; Development Value: Off -; Production Value: Off +; a script is executed. For security reasons, this feature should be disabled +; for non-CLI SAPIs. +; Note: This directive is ignored for the CLI SAPI +; This directive is deprecated. ; https://php.net/register-argc-argv -register_argc_argv = Off +;register_argc_argv = Off ; When enabled, the ENV, REQUEST and SERVER variables are created when they're ; first used (Just In Time) instead of when the script starts. If these @@ -959,8 +948,6 @@ default_socket_timeout = 60 ;extension=xsl ;extension=zip -;zend_extension=opcache - ;;;;;;;;;;;;;;;;;;; ; Module Settings ; ;;;;;;;;;;;;;;;;;;; @@ -1016,8 +1003,12 @@ cli_server.color = On ; This directive allows you to produce PHP errors when some error ; happens within intl functions. The value is the level of the error produced. ; Default is 0, which does not produce any errors. +; This directive is deprecated. ;intl.error_level = E_WARNING -;intl.use_exceptions = 0 +; If enabled this directive indicates that when an error occurs within an +; intl function a IntlException should be thrown. +; Default is Off, which means errors need to be handled manually. +;intl.use_exceptions = On [sqlite3] ; Directory pointing to SQLite3 extensions @@ -1095,6 +1086,14 @@ mail.add_x_header = Off ; RFC 2822 non conformant MTA. mail.mixed_lf_and_crlf = Off +; Control line ending mode for mail messages and headers. +; Possible values: "crlf" (default), "lf", "mixed", "os" +; - crlf: Use CRLF line endings +; - lf: Use LF line endings only (converts CRLF in message to LF) +; - mixed: Same as mail.mixed_lf_and_crlf = On +; - os: Use CRLF on Windows, LF on other systems +mail.cr_lf_mode = crlf + ; The path to a log file that will log all mail() calls. Log entries include ; the full path of the script, line number, To address and headers. ;mail.log = @@ -1318,6 +1317,9 @@ session.use_cookies = 1 ; https://php.net/session.cookie-secure ;session.cookie_secure = +; https://php.net/session.cookie-partitioned +;session.cookie_partitioned = 0 + ; This option forces PHP to fetch and use a cookie for storing and maintaining ; the session id. We encourage this operation as it's very helpful in combating ; session hijacking when not specifying and managing your own session id. It is @@ -1857,6 +1859,14 @@ ldap.max_links = -1 ; SSL stream context option. ;openssl.capath= +; The libctx is an OpenSSL library context. OpenSSL defines a default library +; context, but PHP OpenSSL also defines its own library context to avoid +; interference with other libraries using OpenSSL and to provide an independent +; context for each thread in ZTS. Possible values: +; "custom" - use a custom library context (default) +; "default" - use the default OpenSSL library context +;openssl.libctx=custom + [ffi] ; FFI API restriction. Possible values: ; "preload" - enabled in CLI scripts and preloaded files (default) diff --git a/php.ini-production b/php.ini-production index 042d246943d81..602d005afd54f 100644 --- a/php.ini-production +++ b/php.ini-production @@ -129,11 +129,6 @@ ; Development Value: 4096 ; Production Value: 4096 -; register_argc_argv -; Default Value: On -; Development Value: Off -; Production Value: Off - ; request_order ; Default Value: None ; Development Value: "GP" @@ -327,11 +322,6 @@ serialize_precision = -1 ; https://php.net/disable-functions disable_functions = -; This directive allows you to disable certain classes. -; It receives a comma-delimited list of class names. -; https://php.net/disable-classes -disable_classes = - ; Colors for Syntax Highlighting mode. Anything that's acceptable in ; would work. ; https://php.net/syntax-highlighting @@ -438,6 +428,7 @@ max_input_time = 60 ; Maximum amount of memory a script may consume ; https://php.net/memory-limit memory_limit = 128M +max_memory_limit = -1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Error handling and logging ; @@ -538,12 +529,6 @@ ignore_repeated_errors = Off ; https://php.net/ignore-repeated-source ignore_repeated_source = Off -; If this parameter is set to Off, then memory leaks will not be shown (on -; stdout or in the log). This is only effective in a debug compile, and if -; error reporting includes E_WARNING in the allowed list -; https://php.net/report-memleaks -report_memleaks = On - ; This setting is off by default. ;report_zend_debug = 0 @@ -622,6 +607,12 @@ report_memleaks = On ; Development value: 0 ; Production value: 0 +; This directive controls whether PHP will output the backtrace of fatal errors. +; Default Value: On +; Development Value: On +; Production Value: On +;fatal_error_backtraces = On + ;;;;;;;;;;;;;;;;; ; Data Handling ; ;;;;;;;;;;;;;;;;; @@ -671,14 +662,12 @@ request_order = "GP" ; that were passed when the script was invoked. These arrays are extremely ; useful when running scripts from the command line. When this directive is ; enabled, registering these variables consumes CPU cycles and memory each time -; a script is executed. For performance reasons, this feature should be disabled -; on production servers. -; Note: This directive is hardcoded to On for the CLI SAPI -; Default Value: On -; Development Value: Off -; Production Value: Off +; a script is executed. For security reasons, this feature should be disabled +; for non-CLI SAPIs. +; Note: This directive is ignored for the CLI SAPI +; This directive is deprecated. ; https://php.net/register-argc-argv -register_argc_argv = Off +;register_argc_argv = Off ; When enabled, the ENV, REQUEST and SERVER variables are created when they're ; first used (Just In Time) instead of when the script starts. If these @@ -961,8 +950,6 @@ default_socket_timeout = 60 ;extension=xsl ;extension=zip -;zend_extension=opcache - ;;;;;;;;;;;;;;;;;;; ; Module Settings ; ;;;;;;;;;;;;;;;;;;; @@ -1018,8 +1005,12 @@ cli_server.color = On ; This directive allows you to produce PHP errors when some error ; happens within intl functions. The value is the level of the error produced. ; Default is 0, which does not produce any errors. +; This directive is deprecated. ;intl.error_level = E_WARNING -;intl.use_exceptions = 0 +; If enabled this directive indicates that when an error occurs within an +; intl function a IntlException should be thrown. +; Default is Off, which means errors need to be handled manually. +;intl.use_exceptions = On [sqlite3] ; Directory pointing to SQLite3 extensions @@ -1097,6 +1088,14 @@ mail.add_x_header = Off ; RFC 2822 non conformant MTA. mail.mixed_lf_and_crlf = Off +; Control line ending mode for mail messages and headers. +; Possible values: "crlf" (default), "lf", "mixed", "os" +; - crlf: Use CRLF line endings +; - lf: Use LF line endings only (converts CRLF in message to LF) +; - mixed: Same as mail.mixed_lf_and_crlf = On +; - os: Use CRLF on Windows, LF on other systems +mail.cr_lf_mode = crlf + ; The path to a log file that will log all mail() calls. Log entries include ; the full path of the script, line number, To address and headers. ;mail.log = @@ -1320,6 +1319,9 @@ session.use_cookies = 1 ; https://php.net/session.cookie-secure ;session.cookie_secure = +; https://php.net/session.cookie-partitioned +;session.cookie_partitioned = 0 + ; This option forces PHP to fetch and use a cookie for storing and maintaining ; the session id. We encourage this operation as it's very helpful in combating ; session hijacking when not specifying and managing your own session id. It is @@ -1859,6 +1861,14 @@ ldap.max_links = -1 ; SSL stream context option. ;openssl.capath= +; The libctx is an OpenSSL library context. OpenSSL defines a default library +; context, but PHP OpenSSL also defines its own library context to avoid +; interference with other libraries using OpenSSL and to provide an independent +; context for each thread in ZTS. Possible values: +; "custom" - use a custom library context (default) +; "default" - use the default OpenSSL library context +;openssl.libctx=custom + [ffi] ; FFI API restriction. Possible values: ; "preload" - enabled in CLI scripts and preloaded files (default) diff --git a/run-extra-tests.php b/run-extra-tests.php new file mode 100755 index 0000000000000..725f2b58c3732 --- /dev/null +++ b/run-extra-tests.php @@ -0,0 +1,202 @@ +#!/usr/bin/env php +os}\n"; + echo "CPU Arch: {$environment->cpuArch}\n"; + echo "ZTS: " . ($environment->zts ? 'Yes' : 'No') . "\n"; + echo "DEBUG: " . ($environment->debug ? 'Yes' : 'No') . "\n"; + echo "=====================================================================\n"; + + try { + output_group_start($environment, 'Running Opcache TLS tests'); + if (!run_opcache_tls_tests($environment)) { + echo "Failed\n"; + exit(1); + } + } finally { + output_group_end($environment); + } + + echo "All OK\n"; +} + +function run_opcache_tls_tests(Environment $environment): bool +{ + if (!$environment->zts) { + echo "Skipping: NTS\n"; + return true; + } + + if (!$environment->debug) { + echo "Skipping: NDEBUG\n"; + return true; + } + + $tlsc = ''; + $machine = ''; + $static_support = 'yes'; + + switch ($environment->cpuArch) { + case 'x86': + $machine = '-m32'; + break; + case 'x86_64': + case 'aarch64': + break; + default: + echo "Skipping: {$environment->cpuArch}\n"; + return true; + } + + switch ($environment->os) { + case 'Linux': + case 'FreeBSD': + $tlsc = __DIR__ . "/ext/opcache/jit/tls/zend_jit_tls_{$environment->cpuArch}.c"; + break; + case 'Darwin': + if ($environment->cpuArch === 'aarch64') { + echo "Skipping: JIT+TLS not supported on MacOS Apple Silicon\n"; + return true; + } + $tlsc = __DIR__ . "/ext/opcache/jit/tls/zend_jit_tls_darwin.c"; + $static_support = 'no'; + break; + default: + echo "Skipping: {$environment->os}\n"; + return true; + } + + echo "TLSC=$tlsc MACHINE=$machine STATIC_SUPPORT=$static_support ext/opcache/jit/tls/testing/test.sh\n"; + + $proc = proc_open( + __DIR__ . '/ext/opcache/jit/tls/testing/test.sh', + [ + 0 => ['pipe', 'r'], + ], + $pipes, + env_vars: array_merge(getenv(), [ + 'TLSC' => $tlsc, + 'MACHINE' => $machine, + 'STATIC_SUPPORT' => $static_support, + ]), + ); + + if (!$proc) { + echo "proc_open() failed\n"; + return false; + } + + fclose($pipes[0]); + + return proc_close($proc) === 0; +} + +function output_group_start(Environment $environment, string $name): void +{ + if ($environment->githubAction) { + printf("::group::%s\n", $name); + } else { + printf("%s\n", $name); + } +} + +function output_group_end(Environment $environment): void +{ + if ($environment->githubAction) { + printf("::endgroup::\n"); + } +} + +/** + * Returns getenv('TEST_PHP_OS') if defined, otherwise returns one of + * 'Windows NT', 'Linux', 'FreeBSD', 'Darwin', ... + */ +function detect_os(): string +{ + $os = (string) getenv('TEST_PHP_OS'); + if ($os !== '') { + return $os; + } + + return php_uname('s'); +} + +/** + * Returns getenv('TEST_PHP_CPU_ARCH') if defined, otherwise returns one of + * 'x86', 'x86_64', 'aarch64', ... + */ +function detect_cpu_arch(): string +{ + $cpu = (string) getenv('TEST_PHP_CPU_ARCH'); + if ($cpu !== '') { + return $cpu; + } + + $cpu = php_uname('m'); + if (strtolower($cpu) === 'amd64') { + $cpu = 'x86_64'; + } else if (in_array($cpu, ['i386', 'i686'])) { + $cpu = 'x86'; + } else if ($cpu === 'arm64') { + $cpu = 'aarch64'; + } + + return $cpu; +} + +main($argc, $argv); diff --git a/run-tests.php b/run-tests.php index 036162725673f..171f6e2e5b6d7 100755 --- a/run-tests.php +++ b/run-tests.php @@ -278,7 +278,6 @@ function main(): void 'log_errors=0', 'html_errors=0', 'track_errors=0', - 'report_memleaks=1', 'report_zend_debug=0', 'docref_root=', 'docref_ext=.html', @@ -688,6 +687,10 @@ function main(): void // Run selected tests. $test_cnt = count($test_files); + if ($test_cnt === 1) { + $cfg['show']['diff'] = true; + } + verify_config($php); write_information($user_tests, $phpdbg); diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c index e87223b055e12..88fc584a8bcbb 100644 --- a/sapi/apache2handler/sapi_apache2.c +++ b/sapi/apache2handler/sapi_apache2.c @@ -752,6 +752,7 @@ zend_first_try { static void php_apache_child_init(apr_pool_t *pchild, server_rec *s) { apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null); + php_child_init(); } #ifdef ZEND_SIGNALS diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index e3cd6f49b9f0c..6db96a43ac97b 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -2041,6 +2041,8 @@ consult the installation file that came with this distribution, or visit \n\ */ parent = 0; + php_child_init(); + /* don't catch our signals */ sigaction(SIGTERM, &old_term, 0); sigaction(SIGQUIT, &old_quit, 0); diff --git a/sapi/cgi/tests/001.phpt b/sapi/cgi/tests/001.phpt index c4b539aa83bc6..c990a77efaee1 100644 --- a/sapi/cgi/tests/001.phpt +++ b/sapi/cgi/tests/001.phpt @@ -10,13 +10,12 @@ include "include.inc"; $php = get_cgi_path(); reset_env_vars(); -var_dump(`$php -n -v`); +var_dump(shell_exec("$php -n -v")); echo "Done\n"; ?> --EXPECTF-- string(%d) "PHP %s (cgi%s (built: %s Copyright (c) The PHP Group -%AZend Engine v%s, Copyright (c) Zend Technologies -" +%AZend Engine v%s, Copyright (c) Zend Technologies%A" Done diff --git a/sapi/cgi/tests/002.phpt b/sapi/cgi/tests/002.phpt index b28c8656598cf..374a427cdce94 100644 --- a/sapi/cgi/tests/002.phpt +++ b/sapi/cgi/tests/002.phpt @@ -15,13 +15,13 @@ $file = __DIR__."/002.test.php"; file_put_contents($file, ''); -var_dump(`$php -n -d max_execution_time=111 $file`); -var_dump(`$php -n -d max_execution_time=500 $file`); -var_dump(`$php -n -d max_execution_time=500 -d max_execution_time=555 $file`); +var_dump(shell_exec("$php -n -d max_execution_time=111 $file")); +var_dump(shell_exec("$php -n -d max_execution_time=500 $file")); +var_dump(shell_exec("$php -n -d max_execution_time=500 -d max_execution_time=555 $file")); file_put_contents($file, ''); -var_dump(`$php -n -d upload_tmp_dir=/test/path -d max_execution_time=555 $file`); +var_dump(shell_exec("$php -n -d upload_tmp_dir=/test/path -d max_execution_time=555 $file")); unlink($file); diff --git a/sapi/cgi/tests/003.phpt b/sapi/cgi/tests/003.phpt index ac3f6aa8e6386..81d46e868b3d9 100644 --- a/sapi/cgi/tests/003.phpt +++ b/sapi/cgi/tests/003.phpt @@ -37,9 +37,15 @@ class test { /* {{{ */ file_put_contents($filename, $code); -var_dump(`$php -n -w "$filename"`); -var_dump(`$php -n -w "wrong"`); -var_dump(`echo "" | $php -n -w`); +var_dump(shell_exec(<<" | $php -n -w +SHELL)); @unlink($filename); diff --git a/sapi/cgi/tests/004.phpt b/sapi/cgi/tests/004.phpt index 1de856e346725..fddc5ee80edb5 100644 --- a/sapi/cgi/tests/004.phpt +++ b/sapi/cgi/tests/004.phpt @@ -27,11 +27,17 @@ var_dump(test::$pri); file_put_contents($filename, $code); if (defined("PHP_WINDOWS_VERSION_MAJOR")) { - var_dump(`$php -n -f "$filename"`); + var_dump(shell_exec(<</dev/null`); + var_dump(shell_exec(<</dev/null + SHELL)); } -var_dump(`$php -n -f "wrong"`); +var_dump(shell_exec(<< diff --git a/sapi/cgi/tests/006.phpt b/sapi/cgi/tests/006.phpt index 479d4a9441f26..840dd4329773f 100644 --- a/sapi/cgi/tests/006.phpt +++ b/sapi/cgi/tests/006.phpt @@ -29,8 +29,12 @@ echo test::$var; file_put_contents($filename, $code); -var_dump(`"$php" -n -l "$filename"`); -var_dump(`"$php" -n -l some.unknown`); +var_dump(shell_exec(<<'); -echo (`$php -n $f`); +echo shell_exec("$php -n $f"); echo "Done\n"; diff --git a/sapi/cgi/tests/010.phpt b/sapi/cgi/tests/010.phpt index 67e1a69e26e79..2f5d9a1356d3e 100644 --- a/sapi/cgi/tests/010.phpt +++ b/sapi/cgi/tests/010.phpt @@ -19,19 +19,19 @@ header("HTTP/1.1 403 Forbidden"); header("Status: 403 Also Forbidden"); ?>'); -echo (`$php -n $f`); +echo shell_exec("$php -n $f"); file_put_contents($f, ''); -echo (`$php -n $f`); +echo shell_exec("$php -n $f"); file_put_contents($f, ''); -echo (`$php -n $f`); +echo shell_exec("$php -n $f"); echo "Done\n"; diff --git a/sapi/cgi/tests/include.inc b/sapi/cgi/tests/include.inc index d155edf4ba208..7d38acca8e8dc 100644 --- a/sapi/cgi/tests/include.inc +++ b/sapi/cgi/tests/include.inc @@ -9,7 +9,7 @@ function get_cgi_path() /* {{{ */ $cgi = false; if (file_exists($php) && is_executable($php)) { - $version = `$php_escaped -n -v`; + $version = shell_exec("$php_escaped -n -v"); if (strstr($version, "(cli)")) { /* that's cli */ $cli = true; diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index e212a0f71a23d..460acb62664a6 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -115,7 +115,6 @@ PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks(void) static const char HARDCODED_INI[] = "html_errors=0\n" - "register_argc_argv=1\n" "implicit_flush=1\n" "output_buffering=0\n" "max_execution_time=0\n" diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index b7e3e5fa1be2a..911cfd2bb5910 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -2530,6 +2530,7 @@ static void php_cli_server_startup_workers(void) { #if defined(HAVE_PRCTL) || defined(HAVE_PROCCTL) php_cli_server_worker_install_pdeathsig(); #endif + php_child_init(); return; } else { php_cli_server_workers[php_cli_server_worker] = pid; @@ -2562,7 +2563,11 @@ static zend_result php_cli_server_ctor(php_cli_server *server, const char *addr, server_sock = php_network_listen_socket(host, &port, SOCK_STREAM, &server->address_family, &server->socklen, &errstr); if (server_sock == SOCK_ERR) { - php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to listen on %s:%d (reason: %s)", host, port, errstr ? ZSTR_VAL(errstr) : "?"); + if (strchr(host, ':')) { + php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to listen on [%s]:%d (reason: %s)", host, port, errstr ? ZSTR_VAL(errstr) : "?"); + } else { + php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to listen on %s:%d (reason: %s)", host, port, errstr ? ZSTR_VAL(errstr) : "?"); + } if (errstr) { zend_string_release_ex(errstr, 0); } diff --git a/sapi/cli/tests/001.phpt b/sapi/cli/tests/001.phpt index e13ab8def300f..bb85ad4343577 100644 --- a/sapi/cli/tests/001.phpt +++ b/sapi/cli/tests/001.phpt @@ -7,13 +7,12 @@ version string $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n -v`); +var_dump(shell_exec("$php -n -v")); echo "Done\n"; ?> --EXPECTF-- string(%d) "PHP %s (cli) (built: %s)%s Copyright (c) The PHP Group -%AZend Engine v%s, Copyright (c) Zend Technologies -" +%AZend Engine v%s, Copyright (c) Zend Technologies%A" Done diff --git a/sapi/cli/tests/002-unix.phpt b/sapi/cli/tests/002-unix.phpt index 40e077bf984a8..77a8ee0a7c26a 100644 --- a/sapi/cli/tests/002-unix.phpt +++ b/sapi/cli/tests/002-unix.phpt @@ -12,7 +12,9 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n -r 'var_dump("hello");'`); +var_dump(shell_exec(<< diff --git a/sapi/cli/tests/002.phpt b/sapi/cli/tests/002.phpt index 5c6424f5964cc..81f4f9e33331d 100644 --- a/sapi/cli/tests/002.phpt +++ b/sapi/cli/tests/002.phpt @@ -9,7 +9,9 @@ include "skipif.inc"; $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n -r "var_dump('hello');"`); +var_dump(shell_exec(<< diff --git a/sapi/cli/tests/003-2.phpt b/sapi/cli/tests/003-2.phpt index 88a556b81f503..be1d9d040b506 100644 --- a/sapi/cli/tests/003-2.phpt +++ b/sapi/cli/tests/003-2.phpt @@ -12,8 +12,12 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -nd max_execution_time=111 -r 'var_dump(ini_get("max_execution_time"));'`); -var_dump(`$php -nd max_execution_time=500 -r 'var_dump(ini_get("max_execution_time"));'`); +var_dump(shell_exec(<< --EXPECT-- diff --git a/sapi/cli/tests/003.phpt b/sapi/cli/tests/003.phpt index 20bf61a247bf9..060d831fe767f 100644 --- a/sapi/cli/tests/003.phpt +++ b/sapi/cli/tests/003.phpt @@ -12,10 +12,18 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n -d max_execution_time=111 -r 'var_dump(ini_get("max_execution_time"));'`); -var_dump(`$php -n -d max_execution_time=500 -r 'var_dump(ini_get("max_execution_time"));'`); -var_dump(`$php -n -d max_execution_time=500 -d max_execution_time=555 -r 'var_dump(ini_get("max_execution_time"));'`); -var_dump(`$php -n -d upload_tmp_dir=/test/path -d max_execution_time=555 -r 'var_dump(ini_get("max_execution_time")); var_dump(ini_get("upload_tmp_dir"));'`); +var_dump(shell_exec(<< diff --git a/sapi/cli/tests/004.phpt b/sapi/cli/tests/004.phpt index 83da934c8ff14..c88b85480bdbf 100644 --- a/sapi/cli/tests/004.phpt +++ b/sapi/cli/tests/004.phpt @@ -9,9 +9,9 @@ include "skipif.inc"; $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n --rf unknown`); -var_dump(`$php -n --rf echo`); -var_dump(`$php -n --rf phpinfo`); +var_dump(shell_exec("$php -n --rf unknown")); +var_dump(shell_exec("$php -n --rf echo")); +var_dump(shell_exec("$php -n --rf phpinfo")); echo "Done\n"; ?> diff --git a/sapi/cli/tests/005.phpt b/sapi/cli/tests/005.phpt index 0d8ba066cf7de..ca168ecfe20e3 100644 --- a/sapi/cli/tests/005.phpt +++ b/sapi/cli/tests/005.phpt @@ -9,9 +9,9 @@ include "skipif.inc"; $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n --rc unknown`); -var_dump(`$php -n --rc stdclass`); -var_dump(`$php -n --rc exception`); +var_dump(shell_exec("$php -n --rc unknown")); +var_dump(shell_exec("$php -n --rc stdclass")); +var_dump(shell_exec("$php -n --rc exception")); echo "Done\n"; ?> diff --git a/sapi/cli/tests/006.phpt b/sapi/cli/tests/006.phpt index 38c117ec70f2f..957543c1a28da 100644 --- a/sapi/cli/tests/006.phpt +++ b/sapi/cli/tests/006.phpt @@ -17,9 +17,11 @@ date.timezone=UTC $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n --re unknown`); -var_dump(`$php -n --re ""`); -var_dump(`$php -n --re pcre`); +var_dump(shell_exec("$php -n --re unknown")); +var_dump(shell_exec(<< diff --git a/sapi/cli/tests/007.phpt b/sapi/cli/tests/007.phpt index 6f27586e27d96..afefd2b8ddb9c 100644 --- a/sapi/cli/tests/007.phpt +++ b/sapi/cli/tests/007.phpt @@ -32,9 +32,15 @@ class test { /* {{{ */ file_put_contents($filename, $code); -var_dump(`$php -n -w "$filename"`); -var_dump(`$php -n -w "wrong"`); -var_dump(`echo "" | $php -n -w`); +var_dump(shell_exec(<<" | $php -n -w +SHELL)); @unlink($filename); diff --git a/sapi/cli/tests/008.phpt b/sapi/cli/tests/008.phpt index a8b205056300e..b893473f95f57 100644 --- a/sapi/cli/tests/008.phpt +++ b/sapi/cli/tests/008.phpt @@ -26,8 +26,12 @@ var_dump(test::$pri); file_put_contents($filename, $code); -var_dump(`$php -n -f "$filename"`); -var_dump(`$php -n -f "wrong"`); +var_dump(shell_exec(<< diff --git a/sapi/cli/tests/010-2.phpt b/sapi/cli/tests/010-2.phpt index 1fc05f8cfa35b..88fe1c832a11e 100644 --- a/sapi/cli/tests/010-2.phpt +++ b/sapi/cli/tests/010-2.phpt @@ -22,7 +22,9 @@ hello file_put_contents($filename_txt, $txt); -var_dump(`cat $filename_txt_escaped | $php -n -R "var_dump(1);"`); +var_dump(shell_exec(<< --CLEAN-- diff --git a/sapi/cli/tests/011.phpt b/sapi/cli/tests/011.phpt index d45cb94a08c71..ada916d541631 100644 --- a/sapi/cli/tests/011.phpt +++ b/sapi/cli/tests/011.phpt @@ -26,8 +26,8 @@ echo test::$var; file_put_contents($filename, $code); -var_dump(`$php -n -l $filename_escaped`); -var_dump(`$php -n -l some.unknown`); +var_dump(shell_exec("$php -n -l $filename_escaped")); +var_dump(shell_exec("$php -n -l some.unknown")); $code = ' diff --git a/sapi/cli/tests/012.phpt b/sapi/cli/tests/012.phpt index be21b3d99e87c..47c086724be34 100644 --- a/sapi/cli/tests/012.phpt +++ b/sapi/cli/tests/012.phpt @@ -7,14 +7,14 @@ invalid arguments and error messages $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -var_dump(`$php -n -F some.php -F some.php`); -var_dump(`$php -n -F some.php -R some.php`); -var_dump(`$php -n -R some.php -F some.php`); -var_dump(`$php -n -R some.php -R some.php`); -var_dump(`$php -n -f some.php -f some.php`); -var_dump(`$php -n -B '' -B ''`); -var_dump(`$php -n -E '' -E ''`); -var_dump(`$php -n -r '' -r ''`); +var_dump(shell_exec("$php -n -F some.php -F some.php")); +var_dump(shell_exec("$php -n -F some.php -R some.php")); +var_dump(shell_exec("$php -n -R some.php -F some.php")); +var_dump(shell_exec("$php -n -R some.php -R some.php")); +var_dump(shell_exec("$php -n -f some.php -f some.php")); +var_dump(shell_exec("$php -n -B '' -B ''")); +var_dump(shell_exec("$php -n -E '' -E ''")); +var_dump(shell_exec("$php -n -r '' -r ''")); echo "Done\n"; ?> diff --git a/sapi/cli/tests/013.phpt b/sapi/cli/tests/013.phpt index 345a489403acc..42d4f1eb4c3d2 100644 --- a/sapi/cli/tests/013.phpt +++ b/sapi/cli/tests/013.phpt @@ -16,9 +16,15 @@ $filename_txt = __DIR__."/013.test.txt"; $filename_txt_escaped = escapeshellarg($filename_txt); file_put_contents($filename_txt, "test\nfile\ncontents\n"); -var_dump(`cat $filename_txt_escaped | $php -n -B 'var_dump("start");'`); -var_dump(`cat $filename_txt_escaped | $php -n -E 'var_dump("end");'`); -var_dump(`cat $filename_txt_escaped | $php -n -B 'var_dump("start");' -E 'var_dump("end");'`); +var_dump(shell_exec(<<&1 | grep Usage:`; +echo shell_exec("$php -n --version | grep built:"); +echo shell_exec(<<&1 | grep Usage:"); echo "Done\n"; ?> diff --git a/sapi/cli/tests/016.phpt b/sapi/cli/tests/016.phpt index 544633f592f6d..0ba9027f2164d 100644 --- a/sapi/cli/tests/016.phpt +++ b/sapi/cli/tests/016.phpt @@ -56,7 +56,7 @@ EOT; foreach ($codes as $key => $code) { echo "\n--------------\nSnippet no. $key:\n--------------\n"; $code = escapeshellarg($code); - echo `echo $code | $php -a`, "\n"; + echo shell_exec("echo $code | $php -a"), "\n"; } echo "\nDone\n"; diff --git a/sapi/cli/tests/018.phpt b/sapi/cli/tests/018.phpt index 2511fb852e5bf..ffe92d620590a 100644 --- a/sapi/cli/tests/018.phpt +++ b/sapi/cli/tests/018.phpt @@ -13,7 +13,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -echo `$php -n -m`; +echo shell_exec("$php -n -m"); echo "Done\n"; ?> diff --git a/sapi/cli/tests/019.phpt b/sapi/cli/tests/019.phpt index 0f5a66c871ef2..481ea2228b34c 100644 --- a/sapi/cli/tests/019.phpt +++ b/sapi/cli/tests/019.phpt @@ -13,7 +13,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -echo `$php -n -i`; +echo shell_exec("$php -n -i"); echo "\nDone\n"; ?> diff --git a/sapi/cli/tests/020.phpt b/sapi/cli/tests/020.phpt index 3ccd6a83d3b37..4cffe58e75c9a 100644 --- a/sapi/cli/tests/020.phpt +++ b/sapi/cli/tests/020.phpt @@ -13,8 +13,8 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { $php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); -echo `$php -n --ri this_extension_does_not_exist_568537753423`; -echo `$php -n --ri standard`; +echo shell_exec("$php -n --ri this_extension_does_not_exist_568537753423"); +echo shell_exec("$php -n --ri standard"); echo "\nDone\n"; ?> diff --git a/sapi/cli/tests/021.phpt b/sapi/cli/tests/021.phpt index 9a24ec454a989..9c25d652eb3cc 100644 --- a/sapi/cli/tests/021.phpt +++ b/sapi/cli/tests/021.phpt @@ -31,7 +31,7 @@ $script = "#!$php -n\n". file_put_contents($filename, $script); chmod($filename, 0777); -echo `$filename`; +echo shell_exec($filename); echo "\nDone\n"; ?> diff --git a/sapi/cli/tests/025.phpt b/sapi/cli/tests/025.phpt index f0dcb10753210..c02467d7baf7d 100644 --- a/sapi/cli/tests/025.phpt +++ b/sapi/cli/tests/025.phpt @@ -11,7 +11,7 @@ if (substr(PHP_OS, 0, 3) == 'WIN') { ")); ?> diff --git a/sapi/cli/tests/argv_mb.phpt b/sapi/cli/tests/argv_mb.phpt index f7f6dd49081b0..72df868a04ae7 100644 --- a/sapi/cli/tests/argv_mb.phpt +++ b/sapi/cli/tests/argv_mb.phpt @@ -13,7 +13,7 @@ $argv_fl = __DIR__ . DIRECTORY_SEPARATOR . "argv_test.php"; $argv_fl_escaped = escapeshellarg($argv_fl); file_put_contents($argv_fl, ""); -var_dump(`$php -n $argv_fl_escaped 多字节字符串 マルチバイト文字列 многобайтоваястрока flerbytesträng`); +var_dump(shell_exec("$php -n $argv_fl_escaped 多字节字符串 マルチバイト文字列 многобайтоваястрока flerbytesträng")); @unlink($argv_fl); diff --git a/sapi/cli/tests/argv_mb_bug77111.phpt b/sapi/cli/tests/argv_mb_bug77111.phpt index b26ef7661b5a0..e586049a95aab 100644 --- a/sapi/cli/tests/argv_mb_bug77111.phpt +++ b/sapi/cli/tests/argv_mb_bug77111.phpt @@ -24,7 +24,7 @@ $out_fl = __DIR__ . "\\argv_bug77111.txt"; $argv_fl = __DIR__ . DIRECTORY_SEPARATOR . "argv_bug77111_test.php"; file_put_contents($argv_fl, ""); -`$php -n $argv_fl Ästhetik Æstetik Esthétique Estética Эстетика`; +shell_exec("$php -n $argv_fl Ästhetik Æstetik Esthétique Estética Эстетика"); var_dump(file_get_contents($out_fl)); ?> diff --git a/sapi/cli/tests/bug71624.phpt b/sapi/cli/tests/bug71624.phpt index 83f48cf921c5a..d55bf03f139f6 100644 --- a/sapi/cli/tests/bug71624.phpt +++ b/sapi/cli/tests/bug71624.phpt @@ -22,9 +22,11 @@ file_put_contents($filename_txt, $txt); $test_args = ['$argi', '$argn']; foreach ($test_args as $test_arg) { if (substr(PHP_OS, 0, 3) == 'WIN') { - var_dump(`type $filename_txt_escaped | $php -n -R "echo $test_arg . PHP_EOL;"`); + var_dump(shell_exec(<< --EXPECT-- Interactive shell diff --git a/sapi/cli/tests/gh8827-002.phpt b/sapi/cli/tests/gh8827-002.phpt index 00fd5cfa78f74..712d3e54e509f 100644 --- a/sapi/cli/tests/gh8827-002.phpt +++ b/sapi/cli/tests/gh8827-002.phpt @@ -18,6 +18,7 @@ $stderr = fopen('php://stderr', 'r'); ob_start(function ($buffer) use ($stdout) { fwrite($stdout, $buffer); + return ''; }, 1); print "STDIN:\n"; diff --git a/sapi/cli/tests/gh8827-003.phpt b/sapi/cli/tests/gh8827-003.phpt index 11f7880770ed9..12b6798a57c27 100644 --- a/sapi/cli/tests/gh8827-003.phpt +++ b/sapi/cli/tests/gh8827-003.phpt @@ -34,6 +34,7 @@ file_put_contents('php://fd/2', "Goes to stderrFile\n"); ob_start(function ($buffer) use ($stdoutStream) { fwrite($stdoutStream, $buffer); + return ''; }, 1); print "stdoutFile:\n"; diff --git a/sapi/cli/tests/php_cli_server_ipv4_error_message.phpt b/sapi/cli/tests/php_cli_server_ipv4_error_message.phpt new file mode 100644 index 0000000000000..d00dd3ec9278f --- /dev/null +++ b/sapi/cli/tests/php_cli_server_ipv4_error_message.phpt @@ -0,0 +1,44 @@ +--TEST-- +IPv4 address error message formatting +--SKIPIF-- + +--FILE-- + array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "w") +); + +$process = proc_open( + PHP_BINARY . ' -S "192.168.1.999:8080"', + $descriptorspec, + $pipes +); + +if (is_resource($process)) { + usleep(100000); + + $stderr = stream_get_contents($pipes[2]); + + fclose($pipes[0]); + fclose($pipes[1]); + fclose($pipes[2]); + + proc_terminate($process); + proc_close($process); + + var_dump($stderr); +} +?> +--EXPECTF-- +string(%d) "[%s] Failed to listen on 192.168.1.999:8080 %s +" diff --git a/sapi/cli/tests/php_cli_server_ipv6_error_message.phpt b/sapi/cli/tests/php_cli_server_ipv6_error_message.phpt new file mode 100644 index 0000000000000..55432eeec15e7 --- /dev/null +++ b/sapi/cli/tests/php_cli_server_ipv6_error_message.phpt @@ -0,0 +1,40 @@ +--TEST-- +IPv6 address error message formatting +--SKIPIF-- + +--FILE-- + array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "w") +); + +$process = proc_open( + PHP_BINARY . ' -S "[2001:db8::]:8080"', + $descriptorspec, + $pipes +); + +if (is_resource($process)) { + usleep(100000); + + $stderr = stream_get_contents($pipes[2]); + + fclose($pipes[0]); + fclose($pipes[1]); + fclose($pipes[2]); + + proc_terminate($process); + proc_close($process); + + var_dump($stderr); +} +?> +--EXPECTF-- +string(%d) "[%s] Failed to listen on [2001:db8::]:8080 %s +" diff --git a/sapi/embed/php_embed.c b/sapi/embed/php_embed.c index c18480d07d313..06cd1fb0763b7 100644 --- a/sapi/embed/php_embed.c +++ b/sapi/embed/php_embed.c @@ -25,7 +25,6 @@ static const char HARDCODED_INI[] = "html_errors=0\n" - "register_argc_argv=1\n" "implicit_flush=1\n" "output_buffering=0\n" "max_execution_time=0\n" diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index e18cfebda08f5..63f911af490c7 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -859,7 +859,7 @@ static int fpm_conf_process_all_pools(void) /* alert if user is not set; only if we are root and fpm is not running with --allow-to-run-as-root */ if (!wp->config->user && !geteuid() && !fpm_globals.run_as_root) { - zlog(ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name); + zlog(ZLOG_ALERT, "[pool %s] 'user' directive has not been specified when running as a root without --allow-to-run-as-root", wp->config->name); return -1; } @@ -1383,14 +1383,14 @@ static void fpm_conf_cleanup(int which, void *arg) /* {{{ */ static void fpm_conf_ini_parser_include(char *inc, void *arg) /* {{{ */ { - char *filename; int *error = (int *)arg; php_glob_t g; size_t i; if (!inc || !arg) return; if (*error) return; /* We got already an error. Switch to the end. */ - spprintf(&filename, 0, "%s", ini_filename); + + const char *filename = ini_filename; { g.gl_offs = 0; @@ -1398,31 +1398,26 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg) /* {{{ */ #ifdef PHP_GLOB_NOMATCH if (i == PHP_GLOB_NOMATCH) { zlog(ZLOG_WARNING, "Nothing matches the include pattern '%s' from %s at line %d.", inc, filename, ini_lineno); - efree(filename); return; } #endif /* PHP_GLOB_NOMATCH */ zlog(ZLOG_ERROR, "Unable to globalize '%s' (ret=%zd) from %s at line %d.", inc, i, filename, ini_lineno); *error = 1; - efree(filename); return; } for (i = 0; i < g.gl_pathc; i++) { - int len = strlen(g.gl_pathv[i]); + size_t len = strlen(g.gl_pathv[i]); if (len < 1) continue; if (g.gl_pathv[i][len - 1] == '/') continue; /* don't parse directories */ if (0 > fpm_conf_load_ini_file(g.gl_pathv[i])) { zlog(ZLOG_ERROR, "Unable to include %s from %s at line %d", g.gl_pathv[i], filename, ini_lineno); *error = 1; - efree(filename); return; } } php_globfree(&g); } - - efree(filename); } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_log.c b/sapi/fpm/fpm/fpm_log.c index 6619b7c26f064..87fe4c1d05d75 100644 --- a/sapi/fpm/fpm/fpm_log.c +++ b/sapi/fpm/fpm/fpm_log.c @@ -19,11 +19,10 @@ #include "fastcgi.h" #include "zlog.h" -#define FPM_LOG_BUFFER 1024 - static char *fpm_log_format = NULL; static int fpm_log_fd = -1; static struct key_value_s *fpm_access_suppress_paths = NULL; +static struct zlog_stream fpm_log_stream; static int fpm_access_log_suppress(struct fpm_scoreboard_proc_s *proc); @@ -92,7 +91,8 @@ int fpm_log_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ if (fpm_log_fd == -1) { fpm_log_fd = wp->log_fd; } - + zlog_stream_init_ex(&fpm_log_stream, ZLOG_ACCESS_LOG, fpm_log_fd); + zlog_stream_set_wrapping(&fpm_log_stream, 0); for (wp = fpm_worker_all_pools; wp; wp = wp->next) { if (wp->log_fd > -1 && wp->log_fd != fpm_log_fd) { @@ -107,12 +107,11 @@ int fpm_log_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ int fpm_log_write(char *log_format) /* {{{ */ { - char *s, *b; - char buffer[FPM_LOG_BUFFER+1]; - int token, test; - size_t len, len2; + char *s; + bool test, token = false; struct fpm_scoreboard_proc_s proc, *proc_p; struct fpm_scoreboard_s *scoreboard; + struct zlog_stream *stream; char tmp[129]; char format[129]; time_t now_epoch; @@ -126,9 +125,9 @@ int fpm_log_write(char *log_format) /* {{{ */ if (!log_format) { log_format = fpm_log_format; - test = 0; + test = false; } else { - test = 1; + test = true; } now_epoch = time(NULL); @@ -152,38 +151,25 @@ int fpm_log_write(char *log_format) /* {{{ */ } } - token = 0; - - memset(buffer, '\0', sizeof(buffer)); - b = buffer; - len = 0; - s = log_format; + stream = &fpm_log_stream; + zlog_stream_start(stream); while (*s != '\0') { - /* Test is we have place for 1 more char. */ - if (len >= FPM_LOG_BUFFER) { - zlog(ZLOG_NOTICE, "the log buffer is full (%d). The access log request has been truncated.", FPM_LOG_BUFFER); - len = FPM_LOG_BUFFER; - break; - } - if (!token && *s == '%') { - token = 1; + token = true; memset(format, '\0', sizeof(format)); /* reset format */ s++; continue; } if (token) { - token = 0; - len2 = 0; + token = false; switch (*s) { case '%': /* '%' */ - *b = '%'; - len2 = 1; + zlog_stream_char(stream, '%'); break; #ifdef HAVE_TIMES @@ -207,7 +193,7 @@ int fpm_log_write(char *log_format) /* {{{ */ format[0] = '\0'; if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.); + zlog_stream_format(stream, "%.2f", tms_total / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.); } break; #endif @@ -216,7 +202,7 @@ int fpm_log_write(char *log_format) /* {{{ */ /* seconds */ if (format[0] == '\0' || !strcasecmp(format, "seconds")) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec + proc.duration.tv_usec / 1000000.); + zlog_stream_format(stream, "%.3f", proc.duration.tv_sec + proc.duration.tv_usec / 1000000.); } /* milliseconds */ @@ -225,13 +211,13 @@ int fpm_log_write(char *log_format) /* {{{ */ !strcasecmp(format, "miliseconds") || !strcasecmp(format, "mili") ) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec * 1000. + proc.duration.tv_usec / 1000.); + zlog_stream_format(stream, "%.3f", proc.duration.tv_sec * 1000. + proc.duration.tv_usec / 1000.); } /* microseconds */ } else if (!strcasecmp(format, "microseconds") || !strcasecmp(format, "micro")) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", (unsigned long)(proc.duration.tv_sec * 1000000UL + proc.duration.tv_usec)); + zlog_stream_format(stream, "%lu", (unsigned long)(proc.duration.tv_sec * 1000000UL + proc.duration.tv_usec)); } } else { @@ -249,26 +235,26 @@ int fpm_log_write(char *log_format) /* {{{ */ if (!test) { char *env = fcgi_getenv((fcgi_request*) SG(server_context), format, strlen(format)); - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", env ? env : "-"); + zlog_stream_cstr(stream, env ? env : "-"); } format[0] = '\0'; break; case 'f': /* script */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", *proc.script_filename ? proc.script_filename : "-"); + zlog_stream_cstr(stream, *proc.script_filename ? proc.script_filename : "-"); } break; case 'l': /* content length */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.content_length); + zlog_stream_format(stream, "%zu", proc.content_length); } break; case 'm': /* method */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", *proc.request_method ? proc.request_method : "-"); + zlog_stream_cstr(stream, *proc.request_method ? proc.request_method : "-"); } break; @@ -276,19 +262,19 @@ int fpm_log_write(char *log_format) /* {{{ */ /* seconds */ if (format[0] == '\0' || !strcasecmp(format, "bytes")) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.memory); + zlog_stream_format(stream, "%zu", proc.memory); } /* kilobytes */ } else if (!strcasecmp(format, "kilobytes") || !strcasecmp(format, "kilo")) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.memory / 1024); + zlog_stream_format(stream, "%zu", proc.memory / 1024); } /* megabytes */ } else if (!strcasecmp(format, "megabytes") || !strcasecmp(format, "mega")) { if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.memory / 1024 / 1024); + zlog_stream_format(stream, "%zu", proc.memory / 1024 / 1024); } } else { @@ -300,7 +286,7 @@ int fpm_log_write(char *log_format) /* {{{ */ case 'n': /* pool name */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", scoreboard->pool[0] ? scoreboard->pool : "-"); + zlog_stream_cstr(stream, scoreboard->pool[0] ? scoreboard->pool : "-"); } break; @@ -314,6 +300,7 @@ int fpm_log_write(char *log_format) /* {{{ */ zend_llist_position pos; sapi_headers_struct *sapi_headers = &SG(sapi_headers); size_t format_len = strlen(format); + ssize_t written = 0; h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); while (h) { @@ -339,14 +326,13 @@ int fpm_log_write(char *log_format) /* {{{ */ } header = h->header + format_len + 2; - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", header && *header ? header : "-"); + written += zlog_stream_cstr(stream, header && *header ? header : "-"); /* found, done */ break; } - if (!len2) { - len2 = 1; - *b = '-'; + if (!written) { + zlog_stream_char(stream, '-'); } } format[0] = '\0'; @@ -354,44 +340,44 @@ int fpm_log_write(char *log_format) /* {{{ */ case 'p': /* PID */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%ld", (long)getpid()); + zlog_stream_format(stream, "%ld", (long)getpid()); } break; case 'P': /* PID */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%ld", (long)getppid()); + zlog_stream_format(stream, "%ld", (long)getppid()); } break; case 'q': /* query_string */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.query_string); + zlog_stream_cstr(stream, proc.query_string); } break; case 'Q': /* '?' */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", *proc.query_string ? "?" : ""); + zlog_stream_cstr(stream, *proc.query_string ? "?" : ""); } break; case 'r': /* request URI */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.request_uri); + zlog_stream_cstr(stream, proc.request_uri); } break; case 'R': /* remote IP address */ if (!test) { const char *tmp = fcgi_get_last_client_ip(); - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", tmp ? tmp : "-"); + zlog_stream_cstr(stream, tmp ? tmp : "-"); } break; case 's': /* status */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%d", SG(sapi_headers).http_response_code); + zlog_stream_format(stream, "%d", SG(sapi_headers).http_response_code); } break; @@ -409,14 +395,14 @@ int fpm_log_write(char *log_format) /* {{{ */ } else { strftime(tmp, sizeof(tmp) - 1, format, localtime(t)); } - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", tmp); + zlog_stream_cstr(stream, tmp); } format[0] = '\0'; break; case 'u': /* remote user */ if (!test) { - len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.auth_user); + zlog_stream_cstr(stream, proc.auth_user); } break; @@ -459,30 +445,28 @@ int fpm_log_write(char *log_format) /* {{{ */ return -1; } s++; - if (!test) { - b += len2; - len += len2; - } - if (len >= FPM_LOG_BUFFER) { - zlog(ZLOG_NOTICE, "the log buffer is full (%d). The access log request has been truncated.", FPM_LOG_BUFFER); - len = FPM_LOG_BUFFER; + + if (zlog_stream_is_over_limit(stream)) { + zlog(ZLOG_NOTICE, "the log buffer is over the configured limit. The access log request has been truncated."); break; } continue; } + if (zlog_stream_is_over_limit(stream)) { + zlog(ZLOG_NOTICE, "the log buffer is over the configured limit. The access log request has been truncated."); + break; + } + if (!test) { // push the normal char to the output buffer - *b = *s; - b++; - len++; + zlog_stream_char(stream, *s); } s++; } - if (!test && strlen(buffer) > 0) { - buffer[len] = '\n'; - zend_quiet_write(fpm_log_fd, buffer, len + 1); + if (!test) { + zlog_stream_finish(stream); } return 0; diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index fb02a3e191775..8deb107d0a389 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -41,6 +41,8 @@ static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_ ini_entry->modifiable = mode; } } else { + /* The string wasn't installed and won't be shared, it's safe to drop. */ + GC_MAKE_PERSISTENT_LOCAL(duplicate); zend_string_release_ex(duplicate, 1); } @@ -48,35 +50,6 @@ static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_ } /* }}} */ -static void fpm_php_disable(char *value, int (*zend_disable)(const char *, size_t)) /* {{{ */ -{ - char *s = 0, *e = value; - - while (*e) { - switch (*e) { - case ' ': - case ',': - if (s) { - *e = '\0'; - zend_disable(s, e - s); - s = 0; - } - break; - default: - if (!s) { - s = e; - } - break; - } - e++; - } - - if (s) { - zend_disable(s, e - s); - } -} -/* }}} */ - #define FPM_PHP_INI_ALTERING_ERROR -1 #define FPM_PHP_INI_APPLIED 1 #define FPM_PHP_INI_EXTENSION_FAILED 0 @@ -121,13 +94,6 @@ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ return FPM_PHP_INI_APPLIED; } - if (!strcmp(name, "disable_classes") && *value) { - char *v = strdup(value); - PG(disable_classes) = v; - fpm_php_disable(v, zend_disable_class); - return FPM_PHP_INI_APPLIED; - } - return FPM_PHP_INI_APPLIED; } /* }}} */ @@ -253,6 +219,9 @@ int fpm_php_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ limit_extensions = wp->limit_extensions; wp->limit_extensions = NULL; } + + php_child_init(); + return 0; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h index 5f298a41ae61b..65d243ae53f0d 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.h +++ b/sapi/fpm/fpm/fpm_scoreboard.h @@ -34,11 +34,11 @@ struct fpm_scoreboard_proc_s { struct timeval duration; time_t accepted_epoch; struct timeval tv; - char request_uri[128]; - char query_string[512]; + char request_uri[512]; + char query_string[2048]; char request_method[16]; size_t content_length; /* used with POST only */ - char script_filename[256]; + char script_filename[512]; char auth_user[32]; #ifdef HAVE_TIMES struct tms cpu_accepted; diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c index 39c6eec885bcd..803a768234bd6 100644 --- a/sapi/fpm/fpm/zlog.c +++ b/sapi/fpm/fpm/zlog.c @@ -410,8 +410,16 @@ static inline ssize_t zlog_stream_unbuffered_write( } /* }}} */ -static inline ssize_t zlog_stream_buf_copy_cstr( - struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */ +void zlog_stream_start(struct zlog_stream *stream) +{ + stream->finished = 0; + stream->len = 0; + stream->full = 0; + stream->over_limit = 0; +} + +static ssize_t zlog_stream_buf_copy_cstr( + struct zlog_stream *stream, const char *str, size_t str_len) { ZEND_ASSERT(stream->len <= stream->buf.size); if (stream->buf.size - stream->len <= str_len && @@ -419,25 +427,32 @@ static inline ssize_t zlog_stream_buf_copy_cstr( return -1; } + if (stream->buf.size - stream->len <= str_len) { + stream->over_limit = 1; + str_len = stream->buf.size - stream->len; + } memcpy(stream->buf.data + stream->len, str, str_len); stream->len += str_len; return str_len; } -/* }}} */ -static inline ssize_t zlog_stream_buf_copy_char(struct zlog_stream *stream, char c) /* {{{ */ +static ssize_t zlog_stream_buf_copy_char(struct zlog_stream *stream, char c) { ZEND_ASSERT(stream->len <= stream->buf.size); - if (stream->buf.size - stream->len < 1 && !zlog_stream_buf_alloc_ex(stream, 1)) { + if (stream->buf.size == stream->len && !zlog_stream_buf_alloc_ex(stream, 1)) { return -1; } + if (stream->buf.size == stream->len) { + stream->over_limit = 1; + return 0; + } + stream->buf.data[stream->len++] = c; return 1; } -/* }}} */ static ssize_t zlog_stream_buf_flush(struct zlog_stream *stream) /* {{{ */ { @@ -466,8 +481,8 @@ static ssize_t zlog_stream_buf_flush(struct zlog_stream *stream) /* {{{ */ static ssize_t zlog_stream_buf_append( struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */ { - int over_limit = 0; size_t available_len, required_len, reserved_len; + int over_limit = 0; if (stream->len == 0) { stream->len = zlog_stream_prefix_ex(stream, stream->function, stream->line); @@ -477,7 +492,7 @@ static ssize_t zlog_stream_buf_append( reserved_len = stream->len + stream->msg_suffix_len + stream->msg_quote; required_len = reserved_len + str_len; if (required_len >= zlog_limit) { - over_limit = 1; + stream->over_limit = over_limit = 1; available_len = zlog_limit - reserved_len - 1; } else { available_len = str_len; @@ -521,16 +536,21 @@ static inline void zlog_stream_init_internal( stream->flags = flags; stream->use_syslog = fd == ZLOG_SYSLOG; stream->use_fd = fd > 0; - stream->use_buffer = zlog_buffering || external_logger != NULL || stream->use_syslog; - stream->buf_init_size = capacity; - stream->use_stderr = fd < 0 || - ( - fd != STDERR_FILENO && fd != STDOUT_FILENO && !launched && - (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE - ); - stream->prefix_buffer = (flags & ZLOG_LEVEL_MASK) >= zlog_level && - (stream->use_fd || stream->use_stderr || stream->use_syslog); stream->fd = fd > -1 ? fd : STDERR_FILENO; + stream->buf_init_size = capacity; + if (flags & ZLOG_ACCESS_LOG) { + stream->use_buffer = 1; + stream->use_stderr = fd < 0; + } else { + stream->use_buffer = zlog_buffering || external_logger != NULL || stream->use_syslog; + stream->use_stderr = fd < 0 || + ( + fd != STDERR_FILENO && fd != STDOUT_FILENO && !launched && + (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE + ); + stream->prefix_buffer = (flags & ZLOG_LEVEL_MASK) >= zlog_level && + (stream->use_fd || stream->use_stderr || stream->use_syslog); + } } /* }}} */ @@ -745,7 +765,7 @@ ssize_t zlog_stream_format(struct zlog_stream *stream, const char *fmt, ...) /* } /* }}} */ -ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */ +ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_len) { /* do not write anything if the stream is full or str is empty */ if (str_len == 0 || stream->full) { @@ -754,9 +774,7 @@ ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_ /* reset stream if it is finished */ if (stream->finished) { - stream->finished = 0; - stream->len = 0; - stream->full = 0; + zlog_stream_start(stream); } if (stream->use_buffer) { @@ -765,7 +783,25 @@ ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_ return zlog_stream_unbuffered_write(stream, str, str_len); } -/* }}} */ + +ssize_t zlog_stream_char(struct zlog_stream *stream, char c) +{ + /* do not write anything if the stream is full */ + if (stream->full) { + return 0; + } + + /* reset stream if it is finished */ + if (stream->finished) { + zlog_stream_start(stream); + } + + if (stream->use_buffer) { + return zlog_stream_buf_copy_char(stream, c); + } + const char tmp[1] = {c}; + return zlog_stream_direct_write(stream, tmp, 1); +} static inline void zlog_stream_finish_buffer_suffix(struct zlog_stream *stream) /* {{{ */ { @@ -883,3 +919,8 @@ zlog_bool zlog_stream_close(struct zlog_stream *stream) /* {{{ */ return finished; } /* }}} */ + +zlog_bool zlog_stream_is_over_limit(struct zlog_stream *stream) +{ + return stream->over_limit; +} diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h index be22acc32f3ca..6886a0ae807da 100644 --- a/sapi/fpm/fpm/zlog.h +++ b/sapi/fpm/fpm/zlog.h @@ -48,6 +48,8 @@ enum { #define ZLOG_LEVEL_MASK 7 +#define ZLOG_ACCESS_LOG 16 + #define ZLOG_HAVE_ERRNO 0x100 #define ZLOG_SYSERROR (ZLOG_ERROR | ZLOG_HAVE_ERRNO) @@ -74,6 +76,7 @@ struct zlog_stream { unsigned int msg_quote:1; unsigned int decorate:1; unsigned int is_stdout:1; + unsigned int over_limit:1; int fd; int line; int child_pid; @@ -103,14 +106,22 @@ zlog_bool zlog_stream_set_msg_suffix( struct zlog_stream *stream, const char *suffix, const char *final_suffix); #define zlog_stream_prefix(stream) \ zlog_stream_prefix_ex(stream, __func__, __LINE__) +void zlog_stream_start(struct zlog_stream *stream); ssize_t zlog_stream_prefix_ex(struct zlog_stream *stream, const char *function, int line); ssize_t zlog_stream_format(struct zlog_stream *stream, const char *fmt, ...) __attribute__ ((format(printf,2,3))); ssize_t zlog_stream_vformat(struct zlog_stream *stream, const char *fmt, va_list args); ssize_t zlog_stream_str(struct zlog_stream *stream, const char *str, size_t str_len); +ssize_t zlog_stream_char(struct zlog_stream *stream, char c); zlog_bool zlog_stream_finish(struct zlog_stream *stream); void zlog_stream_destroy(struct zlog_stream *stream); zlog_bool zlog_stream_close(struct zlog_stream *stream); +zlog_bool zlog_stream_is_over_limit(struct zlog_stream *stream); + +static inline ssize_t zlog_stream_cstr(struct zlog_stream *stream, const char *cstr) +{ + return zlog_stream_str(stream, cstr, strlen(cstr)); +} /* default log limit */ #define ZLOG_DEFAULT_LIMIT 1024 diff --git a/sapi/fpm/tests/bug75712-getenv-server-vars_001.phpt b/sapi/fpm/tests/bug75712-getenv-server-vars_001.phpt new file mode 100644 index 0000000000000..05ac22f304e99 --- /dev/null +++ b/sapi/fpm/tests/bug75712-getenv-server-vars_001.phpt @@ -0,0 +1,68 @@ +--TEST-- +FPM: bug75712 - getenv should not read from $_ENV and $_SERVER +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$response = $tester->request(); +echo "=====", PHP_EOL; +$response->printBody(); +echo "=====", PHP_EOL; +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECTF-- +===== +Deprecated: Deriving $_SERVER['argv'] from the query string is deprecated. Configure register_argc_argv=0 to turn this message off in %s on line %d +bool(false) +bool(true) +string(4) "test" +bool(false) +bool(false) +string(2) "dt" +string(2) "dt" +===== +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/bug75712-getenv-server-vars.phpt b/sapi/fpm/tests/bug75712-getenv-server-vars_002.phpt similarity index 88% rename from sapi/fpm/tests/bug75712-getenv-server-vars.phpt rename to sapi/fpm/tests/bug75712-getenv-server-vars_002.phpt index 49d9535a6b03a..b34d936eaf223 100644 --- a/sapi/fpm/tests/bug75712-getenv-server-vars.phpt +++ b/sapi/fpm/tests/bug75712-getenv-server-vars_002.phpt @@ -1,5 +1,5 @@ --TEST-- -FPM: bug75712 - getenv should not read from $_ENV and $_SERVER +FPM: bug75712 - getenv should not read from $_ENV and $_SERVER (register_argc_argv=off) --SKIPIF-- --FILE-- @@ -15,7 +15,7 @@ listen = {{ADDR}} pm = static pm.max_children = 1 env[TEST] = test -php_value[register_argc_argv] = on +php_value[register_argc_argv] = off EOT; $code = << +--FILE-- +start(['--prefix', $prefix]); +$tester->expectLogStartNotices(); +$tester->request(query: 'a=' . str_repeat('a', 1500))->expectBody('OK'); +$tester->expectAccessLog("'GET /log-access-extended-limit.src.php?a=" . str_repeat('a', 1500) . "' 200"); +$tester->request(query: 'a=' . str_repeat('a', 2040))->expectBody('OK'); +$tester->expectAccessLog("'GET /log-access-extended-limit.src.php?a=" . str_repeat('a', 2002) . '...'); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); +$tester->checkAccessLog(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/main-version.phpt b/sapi/fpm/tests/main-version.phpt index 5ae83562d070b..8c7dbe78c92e3 100644 --- a/sapi/fpm/tests/main-version.phpt +++ b/sapi/fpm/tests/main-version.phpt @@ -9,13 +9,12 @@ require_once "tester.inc"; $php = \FPM\Tester::findExecutable(); -var_dump(`$php -n -v`); +var_dump(shell_exec("$php -n -v")); echo "Done\n"; ?> --EXPECTF-- string(%d) "PHP %s (fpm%s (built: %s Copyright (c) The PHP Group -%AZend Engine v%s, Copyright (c) Zend Technologies -" +%AZend Engine v%s, Copyright (c) Zend Technologies%A" Done diff --git a/sapi/fpm/tests/opcache_enable_admin_value.phpt b/sapi/fpm/tests/opcache_enable_admin_value.phpt new file mode 100644 index 0000000000000..2c1081aed9eb8 --- /dev/null +++ b/sapi/fpm/tests/opcache_enable_admin_value.phpt @@ -0,0 +1,49 @@ +--TEST-- +Setting opcache.enable via php_admin_value fails gracefully +--SKIPIF-- + +--FILE-- +start(iniEntries: [ + 'opcache.enable' => '0', + 'opcache.log_verbosity_level' => '2', +]); +$tester->expectLogStartNotices(); +$tester->expectLogPattern("/Zend OPcache can't be temporarily enabled. Are you using php_admin_value\\[opcache.enable\\]=1 in an individual pool's configuration?/"); +echo $tester + ->request() + ->getBody(); +$tester->terminate(); +$tester->close(); + +?> +--EXPECT-- +NULL +--CLEAN-- + diff --git a/sapi/fpm/tests/php_admin_value-failure.phpt b/sapi/fpm/tests/php_admin_value-failure.phpt new file mode 100644 index 0000000000000..dcac2e29c72a8 --- /dev/null +++ b/sapi/fpm/tests/php_admin_value-failure.phpt @@ -0,0 +1,48 @@ +--TEST-- +RC violation on failed php_admin_value +--SKIPIF-- + +--FILE-- +setUserIni($ini); +$tester->start(); +$tester->expectLogStartNotices(); +$tester->request()->expectBody(['string(2) "14"']); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/proc-user-not-set-when-root.phpt b/sapi/fpm/tests/proc-user-not-set-when-root.phpt new file mode 100644 index 0000000000000..4ca68b5156778 --- /dev/null +++ b/sapi/fpm/tests/proc-user-not-set-when-root.phpt @@ -0,0 +1,45 @@ +--TEST-- +FPM: Process user setting unset when running as root +--SKIPIF-- + +--FILE-- +start(envVars: [ + 'TEST_FPM_RUN_AS_ROOT' => 0, +]); +$tester->expectLogAlert( + "'user' directive has not been specified when running as a root without --allow-to-run-as-root", + 'unconfined' +); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/socket-uds-too-long-filename-start.phpt b/sapi/fpm/tests/socket-uds-too-long-filename-start.phpt index a7b43d9519b0a..1baf47a466a42 100644 --- a/sapi/fpm/tests/socket-uds-too-long-filename-start.phpt +++ b/sapi/fpm/tests/socket-uds-too-long-filename-start.phpt @@ -40,11 +40,7 @@ $tester->expectLogPattern( $files = glob($socketFilePrefix . '*'); -if ($files === []) { - echo 'Socket files were not found.' . PHP_EOL; -} - -if ($socketFile === $files[0]) { +if (isset($files[0]) && $socketFile === $files[0]) { // this means the socket file path length is not an issue (anymore). Might be not long enough echo 'Socket file is the same as configured.' . PHP_EOL; } diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index f486309085e6d..9079886543378 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -540,7 +540,7 @@ class Tester $cmd[] = '-d' . $iniEntryName . '=' . $iniEntryValue; } - if (getenv('TEST_FPM_RUN_AS_ROOT')) { + if ($envVars['TEST_FPM_RUN_AS_ROOT'] ?? getenv('TEST_FPM_RUN_AS_ROOT')) { $cmd[] = '--allow-to-run-as-root'; } $cmd = array_merge($cmd, $extraArgs); diff --git a/sapi/fpm/www.conf.in b/sapi/fpm/www.conf.in index 9689e4defab04..69df3e6630047 100644 --- a/sapi/fpm/www.conf.in +++ b/sapi/fpm/www.conf.in @@ -474,9 +474,8 @@ pm.max_spare_servers = 3 ; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. ; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. +; extension_dir. Defining 'disable_functions' will not overwrite previously +; defined php.ini values, but will append the new value instead. ; Note: path INI options can be relative and will be expanded with the prefix ; (pool, global or @prefix@) diff --git a/sapi/fuzzer/README.md b/sapi/fuzzer/README.md index b4bb2bbe4573f..42e1eb7fa3040 100644 --- a/sapi/fuzzer/README.md +++ b/sapi/fuzzer/README.md @@ -31,8 +31,8 @@ When running `make` it creates these binaries in `sapi/fuzzer/`: * `php-fuzz-mbstring`: Fuzzing `mb_convert_encoding()` (requires `--enable-mbstring`) * `php-fuzz-mbregex`: Fuzzing `mb_ereg[i]()` (requires --enable-mbstring) * `php-fuzz-execute`: Fuzzing the executor -* `php-fuzz-function-jit`: Fuzzing the function JIT (requires --enable-opcache) -* `php-fuzz-tracing-jit`: Fuzzing the tracing JIT (requires --enable-opcache) +* `php-fuzz-function-jit`: Fuzzing the function JIT +* `php-fuzz-tracing-jit`: Fuzzing the tracing JIT Some fuzzers have a seed corpus in `sapi/fuzzer/corpus`. You can use it as follows: diff --git a/sapi/fuzzer/fuzzer-execute-common.h b/sapi/fuzzer/fuzzer-execute-common.h index f5113a5b0e41f..338c771e551a3 100644 --- a/sapi/fuzzer/fuzzer-execute-common.h +++ b/sapi/fuzzer/fuzzer-execute-common.h @@ -23,6 +23,7 @@ #include "fuzzer.h" #include "fuzzer-sapi.h" #include "zend_exceptions.h" +#include "zend_vm.h" #define FILE_NAME "/tmp/fuzzer.php" #define MAX_STEPS 1000 @@ -32,10 +33,6 @@ static uint32_t steps_left; static bool bailed_out = false; -/* Because the fuzzer is always compiled with clang, - * we can assume that we don't use global registers / hybrid VM. */ -typedef zend_op *(ZEND_FASTCALL *opcode_handler_t)(zend_execute_data *, const zend_op *); - static zend_always_inline void fuzzer_bailout(void) { bailed_out = true; zend_bailout(); @@ -53,10 +50,21 @@ static zend_always_inline void fuzzer_step(void) { static void (*orig_execute_ex)(zend_execute_data *execute_data); static void fuzzer_execute_ex(zend_execute_data *execute_data) { + +#ifdef ZEND_CHECK_STACK_LIMIT + if (UNEXPECTED(zend_call_stack_overflowed(EG(stack_limit)))) { + zend_call_stack_size_error(); + /* No opline was executed before exception */ + EG(opline_before_exception) = NULL; + /* Fall through to handle exception below. */ + } +#endif /* ZEND_CHECK_STACK_LIMIT */ + const zend_op *opline = EX(opline); + while (1) { fuzzer_step(); - opline = ((opcode_handler_t) opline->handler)(execute_data, opline); + opline = ((zend_vm_opcode_handler_func_t) zend_get_opcode_handler_func(opline))(execute_data, opline); if ((uintptr_t) opline & ZEND_VM_ENTER_BIT) { opline = (const zend_op *) ((uintptr_t) opline & ~ZEND_VM_ENTER_BIT); if (opline) { @@ -127,44 +135,15 @@ ZEND_ATTRIBUTE_UNUSED static void create_file(void) { ZEND_ATTRIBUTE_UNUSED static void opcache_invalidate(void) { steps_left = MAX_STEPS; zend_exception_save(); - zval retval, func, args[2]; - ZVAL_STRING(&func, "opcache_invalidate"); + zval retval, args[2]; + zend_function *fn = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("opcache_invalidate")); + ZEND_ASSERT(fn != NULL); + ZVAL_STRING(&args[0], FILE_NAME); ZVAL_TRUE(&args[1]); - call_user_function(CG(function_table), NULL, &func, &retval, 2, args); + zend_call_known_function(fn, NULL, NULL, &retval, 2, args, NULL); ZEND_ASSERT(Z_TYPE(retval) == IS_TRUE); zval_ptr_dtor(&args[0]); zval_ptr_dtor(&retval); - zval_ptr_dtor(&func); zend_exception_restore(); } - -ZEND_ATTRIBUTE_UNUSED char *get_opcache_path(void) { - /* Try relative to cwd. */ - char *p = realpath("modules/opcache.so", NULL); - if (p) { - return p; - } - - /* Try relative to binary location. */ - char path[MAXPATHLEN]; -#if defined(__FreeBSD__) - size_t pathlen = sizeof(path); - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; - if (sysctl(mib, 4, path, &pathlen, NULL, 0) < 0) { -#else - if (readlink("/proc/self/exe", path, sizeof(path)) < 0) { -#endif - ZEND_ASSERT(0 && "Failed to get binary path"); - return NULL; - } - - /* Get basename. */ - char *last_sep = strrchr(path, '/'); - if (last_sep) { - *last_sep = '\0'; - } - - strlcat(path, "/modules/opcache.so", sizeof(path)); - return realpath(path, NULL); -} diff --git a/sapi/fuzzer/fuzzer-function-jit.c b/sapi/fuzzer/fuzzer-function-jit.c index 92415c2a0e125..d2117f0027c47 100644 --- a/sapi/fuzzer/fuzzer-function-jit.c +++ b/sapi/fuzzer/fuzzer-function-jit.c @@ -50,18 +50,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { } int LLVMFuzzerInitialize(int *argc, char ***argv) { - char *opcache_path = get_opcache_path(); - assert(opcache_path && "Failed to determine opcache path"); - char ini_buf[512]; snprintf(ini_buf, sizeof(ini_buf), - "zend_extension=%s\n" "opcache.validate_timestamps=0\n" "opcache.file_update_protection=0\n" "opcache.jit_buffer_size=128M\n" - "opcache.protect_memory=1\n", - opcache_path); - free(opcache_path); + "opcache.protect_memory=1\n"); create_file(); fuzzer_init_php_for_execute(ini_buf); diff --git a/sapi/fuzzer/fuzzer-sapi.c b/sapi/fuzzer/fuzzer-sapi.c index baf77ae0463b3..b1909ef2f42fa 100644 --- a/sapi/fuzzer/fuzzer-sapi.c +++ b/sapi/fuzzer/fuzzer-sapi.c @@ -45,7 +45,7 @@ static const char HARDCODED_INI[] = "allow_url_include=0\n" "allow_url_fopen=0\n" "open_basedir=/tmp\n" - "disable_functions=dl,mail,mb_send_mail" + "disable_functions=dl,mail,mb_send_mail,set_error_handler" ",shell_exec,exec,system,proc_open,popen,passthru,pcntl_exec" ",chdir,chgrp,chmod,chown,copy,file_put_contents,lchgrp,lchown,link,mkdir" ",move_uploaded_file,rename,rmdir,symlink,tempname,touch,unlink,fopen" @@ -56,8 +56,6 @@ static const char HARDCODED_INI[] = ",crypt" /* openlog() has a known memory-management issue. */ ",openlog" - /* Can cause long loops that bypass the executor step limit. */ - "\ndisable_classes=InfiniteIterator" ; static int startup(sapi_module_struct *sapi_module) @@ -128,6 +126,25 @@ static sapi_module_struct fuzzer_module = { STANDARD_SAPI_MODULE_PROPERTIES }; +static ZEND_COLD zend_function *disable_class_get_constructor_handler(zend_object *obj) /* {{{ */ +{ + zend_throw_error(NULL, "Cannot construct class %s, as it is disabled", ZSTR_VAL(obj->ce->name)); + return NULL; +} + +static void fuzzer_disable_classes(void) +{ + /* Overwrite built-in constructor for InfiniteIterator as it + * can cause long loops that bypass the executor step limit. */ + /* Lowercase as this is how the CE as stored */ + zend_class_entry *InfiniteIterator_class = zend_hash_str_find_ptr(CG(class_table), "infiniteiterator", strlen("infiniteiterator")); + + static zend_object_handlers handlers; + memcpy(&handlers, InfiniteIterator_class->default_object_handlers, sizeof(handlers)); + handlers.get_constructor = disable_class_get_constructor_handler; + InfiniteIterator_class->default_object_handlers = &handlers; +} + int fuzzer_init_php(const char *extra_ini) { #ifdef __SANITIZE_ADDRESS__ @@ -183,6 +200,8 @@ int fuzzer_request_startup(void) SIGG(check) = 0; #endif + fuzzer_disable_classes(); + return SUCCESS; } @@ -292,11 +311,13 @@ int fuzzer_do_request_from_buffer( // Call named PHP function with N zval arguments void fuzzer_call_php_func_zval(const char *func_name, int nargs, zval *args) { - zval retval, func; + zval retval; + + zend_function *fn = zend_hash_str_find_ptr(CG(function_table), func_name, strlen(func_name)); + ZEND_ASSERT(fn != NULL); - ZVAL_STRING(&func, func_name); ZVAL_UNDEF(&retval); - call_user_function(CG(function_table), NULL, &func, &retval, nargs, args); + zend_call_known_function(fn, NULL, NULL, &retval, nargs, args, NULL); // TODO: check result? /* to ensure retval is not broken */ @@ -304,7 +325,6 @@ void fuzzer_call_php_func_zval(const char *func_name, int nargs, zval *args) { /* cleanup */ zval_ptr_dtor(&retval); - zval_ptr_dtor(&func); } // Call named PHP function with N string arguments diff --git a/sapi/fuzzer/fuzzer-tracing-jit.c b/sapi/fuzzer/fuzzer-tracing-jit.c index 437938d090278..65d661f139cf3 100644 --- a/sapi/fuzzer/fuzzer-tracing-jit.c +++ b/sapi/fuzzer/fuzzer-tracing-jit.c @@ -54,12 +54,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { } int LLVMFuzzerInitialize(int *argc, char ***argv) { - char *opcache_path = get_opcache_path(); - assert(opcache_path && "Failed to determine opcache path"); - char ini_buf[512]; snprintf(ini_buf, sizeof(ini_buf), - "zend_extension=%s\n" "opcache.validate_timestamps=0\n" "opcache.file_update_protection=0\n" "opcache.memory_consumption=1024\n" @@ -71,9 +67,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) { "opcache.jit_max_root_traces=100000\n" "opcache.jit_max_side_traces=100000\n" "opcache.jit_max_exit_counters=100000\n" - "opcache.protect_memory=1\n", - opcache_path); - free(opcache_path); + "opcache.protect_memory=1\n"); create_file(); fuzzer_init_php_for_execute(ini_buf); diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c index 432c0338c46da..75dc721240e69 100644 --- a/sapi/litespeed/lsapi_main.c +++ b/sapi/litespeed/lsapi_main.c @@ -591,7 +591,7 @@ static int sapi_lsapi_activate(void) static sapi_module_struct lsapi_sapi_module = { "litespeed", - "LiteSpeed V8.2", + "LiteSpeed V8.3", php_lsapi_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ @@ -1395,6 +1395,8 @@ void start_children( int children ) switch( pid ) { case 0: /* children process */ + php_child_init(); + /* don't catch our signals */ sigaction( SIGTERM, &old_term, 0 ); sigaction( SIGQUIT, &old_quit, 0 ); diff --git a/sapi/litespeed/lscriu.c b/sapi/litespeed/lscriu.c index 09ad53e233c62..042f5fb7a2b5c 100644 --- a/sapi/litespeed/lscriu.c +++ b/sapi/litespeed/lscriu.c @@ -85,6 +85,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "lscriu.h" #include +#include "main/php_main.h" #define LSCRIU_PATH 256 @@ -459,6 +460,7 @@ static void LSCRIU_CloudLinux_Checkpoint(void) else { s_restored = 1; LSAPI_reset_server_state(); + php_child_init(); /* Here we have restored the php process, so we should to tell (via semaphore) mod_lsapi that we are started and ready to receive data. @@ -532,6 +534,7 @@ static void LSCRIU_try_checkpoint(int *forked_pid) LSCRIU_Wait_Dump_Finish_Or_Restored(iPidParent); LSCRIU_Restored_Error(0, "Restored!"); LSAPI_reset_server_state(); + php_child_init(); s_restored = 1; } else { diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index c169c11bfbb77..bc2bb08c70278 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -982,7 +982,6 @@ static const opt_struct OPTIONS[] = { /* {{{ */ const char phpdbg_ini_hardcoded[] = "html_errors=Off\n" -"register_argc_argv=On\n" "implicit_flush=On\n" "display_errors=Off\n" "log_errors=On\n" diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 0a94adf21305a..ccbccc32f711b 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -1206,14 +1206,14 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num) /* {{{ */ name = estrdup(brake->name); name_len = strlen(name); if (zend_hash_num_elements(&PHPDBG_G(bp)[type]) == 1) { - PHPDBG_G(flags) &= ~(1<<(brake->type+1)); + PHPDBG_G(flags) &= ~(1ull<<(brake->type+1)); } } break; default: { if (zend_hash_num_elements(table) == 1) { - PHPDBG_G(flags) &= ~(1<<(brake->type+1)); + PHPDBG_G(flags) &= ~(1ull<<(brake->type+1)); } } } diff --git a/sapi/phpdbg/phpdbg_lexer.l b/sapi/phpdbg/phpdbg_lexer.l index 60d995526ea27..ba1423c5a4ecd 100644 --- a/sapi/phpdbg/phpdbg_lexer.l +++ b/sapi/phpdbg/phpdbg_lexer.l @@ -77,7 +77,7 @@ T_IF 'if' T_RUN 'run' T_RUN_SHORT "r" WS [ \r\t]+ -DIGITS [-]?[0-9\.]+ +DIGITS [-]?[0-9.]+ ID [^ \r\n\t:#\000]+ GENERIC_ID ([^ \r\n\t:#\000"']|":\\")+|["]([^\n\000"\\]|"\\\\"|"\\"["])+["]|[']([^\n\000'\\]|"\\\\"|"\\"['])+['] ADDR [0][x][a-fA-F0-9]+ diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 84bd7a076acec..7215888cb25ec 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -41,7 +41,7 @@ #include "phpdbg_lexer.h" #include "phpdbg_parser.h" -#if ZEND_VM_KIND != ZEND_VM_KIND_CALL && ZEND_VM_KIND != ZEND_VM_KIND_HYBRID +#if ZEND_VM_KIND != ZEND_VM_KIND_CALL && ZEND_VM_KIND != ZEND_VM_KIND_TAILCALL && ZEND_VM_KIND != ZEND_VM_KIND_HYBRID #error "phpdbg can only be built with CALL zend vm kind" #endif @@ -111,7 +111,7 @@ static inline int phpdbg_call_register(phpdbg_param_t *stack) /* {{{ */ array_init(¶ms); while (next) { - char *buffered = NULL; + zend_string *buffered = NULL; switch (next->type) { case OP_PARAM: @@ -125,28 +125,28 @@ static inline int phpdbg_call_register(phpdbg_param_t *stack) /* {{{ */ break; case METHOD_PARAM: - spprintf(&buffered, 0, "%s::%s", next->method.class, next->method.name); - add_next_index_string(¶ms, buffered); + buffered = strpprintf(0, "%s::%s", next->method.class, next->method.name); + add_next_index_str(¶ms, buffered); break; case NUMERIC_METHOD_PARAM: - spprintf(&buffered, 0, "%s::%s#"ZEND_LONG_FMT, next->method.class, next->method.name, next->num); - add_next_index_string(¶ms, buffered); + buffered = strpprintf(0, "%s::%s#"ZEND_LONG_FMT, next->method.class, next->method.name, next->num); + add_next_index_str(¶ms, buffered); break; case NUMERIC_FUNCTION_PARAM: - spprintf(&buffered, 0, "%s#"ZEND_LONG_FMT, next->str, next->num); - add_next_index_string(¶ms, buffered); + buffered = strpprintf(0, "%s#"ZEND_LONG_FMT, next->str, next->num); + add_next_index_str(¶ms, buffered); break; case FILE_PARAM: - spprintf(&buffered, 0, "%s:"ZEND_ULONG_FMT, next->file.name, next->file.line); - add_next_index_string(¶ms, buffered); + buffered = strpprintf(0, "%s:"ZEND_ULONG_FMT, next->file.name, next->file.line); + add_next_index_str(¶ms, buffered); break; case NUMERIC_FILE_PARAM: - spprintf(&buffered, 0, "%s:#"ZEND_ULONG_FMT, next->file.name, next->file.line); - add_next_index_string(¶ms, buffered); + buffered = strpprintf(0, "%s:#"ZEND_ULONG_FMT, next->file.name, next->file.line); + add_next_index_str(¶ms, buffered); break; default: { diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index 4478dca0516ba..5657649efdb69 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -139,7 +139,7 @@ bool phpdbg_check_watch_diff(phpdbg_watchtype type, void *oldPtr, void *newPtr) switch (type) { case WATCH_ON_BUCKET: if (memcmp(&((Bucket *) oldPtr)->h, &((Bucket *) newPtr)->h, sizeof(Bucket) - sizeof(zval) /* hash+key comparison */) != 0) { - return 2; + return true; } /* Fall through to also compare the value from the bucket. */ ZEND_FALLTHROUGH; @@ -154,7 +154,7 @@ bool phpdbg_check_watch_diff(phpdbg_watchtype type, void *oldPtr, void *newPtr) case WATCH_ON_HASHDATA: ZEND_UNREACHABLE(); } - return 0; + return false; } void phpdbg_print_watch_diff(phpdbg_watchtype type, zend_string *name, void *oldPtr, void *newPtr) { @@ -280,9 +280,9 @@ static inline void phpdbg_deactivate_watchpoint(phpdbg_watchpoint_t *watch) { /* Note that consecutive pages need to be merged in order to avoid watchpoints spanning page boundaries to have part of their data in the one page, part in the other page */ #ifdef _WIN32 -int phpdbg_watchpoint_segfault_handler(void *addr) { +zend_result phpdbg_watchpoint_segfault_handler(void *addr) { #else -int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context) { +zend_result phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context) { #endif void *page = phpdbg_get_page_boundary( @@ -562,12 +562,12 @@ bool phpdbg_is_recursively_watched(void *ptr, phpdbg_watch_element *element) { do { element = next; if (element->watch->addr.ptr == ptr) { - return 1; + return true; } next = element->parent; } while (!(element->flags & PHPDBG_WATCH_RECURSIVE_ROOT)); - return 0; + return false; } void phpdbg_add_recursive_watch_from_ht(phpdbg_watch_element *element, zend_long idx, zend_string *str, zval *zv) { @@ -721,7 +721,7 @@ bool phpdbg_try_re_adding_watch_element(zval *parent, phpdbg_watch_element *elem HashTable *ht = HT_FROM_ZVP(parent); if (!ht) { - return 0; + return false; } else if (element->flags & (PHPDBG_WATCH_ARRAY | PHPDBG_WATCH_OBJECT)) { char *htPtr = ((char *) ht) + HT_WATCH_OFFSET; char *oldPtr = ((char *) &element->backup.ht) + HT_WATCH_OFFSET; @@ -742,7 +742,7 @@ bool phpdbg_try_re_adding_watch_element(zval *parent, phpdbg_watch_element *elem } if (!phpdbg_try_re_adding_watch_element(next, element->child)) { - return 0; + return false; } } else if (phpdbg_check_watch_diff(WATCH_ON_ZVAL, &element->backup.zv, zv)) { phpdbg_print_watch_diff(WATCH_ON_ZVAL, element->str, &element->backup.zv, zv); @@ -752,10 +752,10 @@ bool phpdbg_try_re_adding_watch_element(zval *parent, phpdbg_watch_element *elem phpdbg_add_bucket_watch_element((Bucket *) zv, element); phpdbg_watch_parent_ht(element); } else { - return 0; + return false; } - return 1; + return true; } void phpdbg_automatic_dequeue_free(phpdbg_watch_element *element) { @@ -1481,7 +1481,7 @@ void phpdbg_setup_watchpoints(void) { #ifdef HAVE_USERFAULTFD_WRITEFAULT int flags = O_CLOEXEC; #ifdef UFFD_USER_MODE_ONLY - // unpriviliged userfaultfd are disabled by default, + // unprivileged userfaultfd are disabled by default, // with this flag it allows ranges from the user space // being reported. flags |= UFFD_USER_MODE_ONLY; diff --git a/sapi/phpdbg/phpdbg_watch.h b/sapi/phpdbg/phpdbg_watch.h index 17d9dfac93ddd..56f4b29379ca6 100644 --- a/sapi/phpdbg/phpdbg_watch.h +++ b/sapi/phpdbg/phpdbg_watch.h @@ -115,9 +115,9 @@ void phpdbg_destroy_watchpoints(void); void phpdbg_purge_watchpoint_tree(void); #ifndef _WIN32 -int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context); +zend_result phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context); #else -int phpdbg_watchpoint_segfault_handler(void *addr); +zend_result phpdbg_watchpoint_segfault_handler(void *addr); #endif void phpdbg_create_addr_watchpoint(void *addr, size_t size, phpdbg_watchpoint_t *watch); diff --git a/sapi/phpdbg/tests/bug73615.phpt b/sapi/phpdbg/tests/bug73615.phpt index 2208cdebf707b..843424d7b3695 100644 --- a/sapi/phpdbg/tests/bug73615.phpt +++ b/sapi/phpdbg/tests/bug73615.phpt @@ -11,7 +11,7 @@ $phpdbg = getenv('TEST_PHPDBG_EXECUTABLE_ESCAPED'); chdir(__DIR__."/bug73615"); -print `$phpdbg -qn`; +print shell_exec("$phpdbg -qn"); ?> --EXPECT-- diff --git a/scripts/dev/bless_tests.php b/scripts/dev/bless_tests.php index 03927cfd0055c..58baeac402462 100755 --- a/scripts/dev/bless_tests.php +++ b/scripts/dev/bless_tests.php @@ -65,7 +65,7 @@ function normalizeOutput(string $out): string { $out = preg_replace('/in (\/|[A-Z]:\\\\)\S+ on line \d+/m', 'in %s on line %d', $out); $out = preg_replace('/in (\/|[A-Z]:\\\\)\S+:\d+/m', 'in %s:%d', $out); $out = preg_replace('/\{closure:(\/|[A-Z]:\\\\)\S+:\d+\}/', '{closure:%s:%d}', $out); - $out = preg_replace('/object\(([A-Za-z0-9]*)\)#\d+/', 'object($1)#%d', $out); + $out = preg_replace('/object\(([A-Za-z0-9\\\\]*)\)#\d+/', 'object($1)#%d', $out); $out = preg_replace('/^#(\d+) (\/|[A-Z]:\\\\)\S+\(\d+\):/m', '#$1 %s(%d):', $out); $out = preg_replace('/Resource id #\d+/', 'Resource id #%d', $out); $out = preg_replace('/resource\(\d+\) of type/', 'resource(%d) of type', $out); diff --git a/tests/basic/011.phpt b/tests/basic/011.phpt index 03fccaa9b704d..0a65b4975a95e 100644 --- a/tests/basic/011.phpt +++ b/tests/basic/011.phpt @@ -1,5 +1,9 @@ --TEST-- Testing $argc and $argv handling (GET) +--SKIPIF-- + --INI-- register_argc_argv=1 --GET-- @@ -14,7 +18,8 @@ for ($i=0; $i<$argc; $i++) { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Deriving $_SERVER['argv'] from the query string is deprecated. Configure register_argc_argv=0 to turn this message off in %s on line %d 0: ab 1: cd 2: ef diff --git a/tests/basic/011_empty_query.phpt b/tests/basic/011_empty_query.phpt new file mode 100644 index 0000000000000..a6e8ad8ef9b87 --- /dev/null +++ b/tests/basic/011_empty_query.phpt @@ -0,0 +1,20 @@ +--TEST-- +Testing $argc and $argv handling (GET empty) +--SKIPIF-- + +--INI-- +register_argc_argv=1 +--CGI-- +--FILE-- + +--EXPECTF-- +Deprecated: Deriving $_SERVER['argv'] from the query string is deprecated. Configure register_argc_argv=0 to turn this message off in %s on line %d +int(0) +array(0) { +} diff --git a/tests/basic/011_register_argc_argv_disabled.phpt b/tests/basic/011_register_argc_argv_disabled.phpt new file mode 100644 index 0000000000000..0947a911dd0ff --- /dev/null +++ b/tests/basic/011_register_argc_argv_disabled.phpt @@ -0,0 +1,22 @@ +--TEST-- +Testing $argc and $argv handling (GET, register_argc_argv=0) +--SKIPIF-- + +--INI-- +register_argc_argv=0 +--GET-- +ab+cd+ef+123+test +--FILE-- + +--EXPECTF-- +Warning: Undefined array key "argc" in %s on line %d + +Warning: Undefined array key "argv" in %s on line %d +NULL +NULL diff --git a/tests/basic/011_windows.phpt b/tests/basic/011_windows.phpt new file mode 100644 index 0000000000000..c25853f98c5f5 --- /dev/null +++ b/tests/basic/011_windows.phpt @@ -0,0 +1,23 @@ +--TEST-- +Testing $argc and $argv handling (GET) +--INI-- +register_argc_argv=1 +--GET-- +foo=ab+cd+ef+123+test +--FILE-- + +--EXPECTF-- +Deprecated: Deriving $_SERVER['argv'] from the query string is deprecated. Configure register_argc_argv=0 to turn this message off in %s on line %d +0: foo=ab +1: cd +2: ef +3: 123 +4: test diff --git a/tests/basic/012_register_argc_argv_disabled.phpt b/tests/basic/012_register_argc_argv_disabled.phpt new file mode 100644 index 0000000000000..415e39074f3b6 --- /dev/null +++ b/tests/basic/012_register_argc_argv_disabled.phpt @@ -0,0 +1,49 @@ +--TEST-- +Testing $argc and $argv handling (cli, register_argc_argv=0) +--INI-- +register_argc_argv=0 +variables_order=GPS +--ARGS-- +ab cd ef 123 test +--FILE-- + +--EXPECTF-- +int(6) +array(6) { + [0]=> + string(%d) "%s" + [1]=> + string(2) "ab" + [2]=> + string(2) "cd" + [3]=> + string(2) "ef" + [4]=> + string(3) "123" + [5]=> + string(4) "test" +} +int(6) +array(6) { + [0]=> + string(%d) "%s" + [1]=> + string(2) "ab" + [2]=> + string(2) "cd" + [3]=> + string(2) "ef" + [4]=> + string(3) "123" + [5]=> + string(4) "test" +} diff --git a/tests/basic/array_key_exists_null_deprecation.phpt b/tests/basic/array_key_exists_null_deprecation.phpt new file mode 100644 index 0000000000000..5087ec3362ae7 --- /dev/null +++ b/tests/basic/array_key_exists_null_deprecation.phpt @@ -0,0 +1,13 @@ +--TEST-- +Deprecate using null as key in array_key_exists() +--FILE-- + 'bar', '' => 'baz']; + +var_dump(array_key_exists(null, $arr)); +var_dump(array_key_exists('', $arr)); +?> +--EXPECTF-- +Deprecated: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead in %s on line %d +bool(true) +bool(true) diff --git a/tests/basic/array_null_offset_deprecation.phpt b/tests/basic/array_null_offset_deprecation.phpt new file mode 100644 index 0000000000000..fdc4134522a1d --- /dev/null +++ b/tests/basic/array_null_offset_deprecation.phpt @@ -0,0 +1,27 @@ +--TEST-- +Deprecate using null as array offset +--FILE-- + 'bar', '' => 'baz']; + +echo $arr[null] . "\n"; + +$arr[null] = 'new_value'; +echo $arr[''] . "\n"; + +var_dump(isset($arr[null])); + +unset($arr[null]); +var_dump(isset($arr[''])); +?> +--EXPECTF-- + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d +baz + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d +new_value + +Deprecated: Using null as an array offset is deprecated, use an empty string instead in %s on line %d +bool(true) +bool(false) diff --git a/tests/basic/bug31875.phpt b/tests/basic/bug31875.phpt index 0fdc134d6373b..ee9b466fa7d85 100644 --- a/tests/basic/bug31875.phpt +++ b/tests/basic/bug31875.phpt @@ -22,6 +22,8 @@ var_dump(in_array($disabled_function, $functions['internal'])); --EXPECTF-- bool(false) -Deprecated: get_defined_functions(): Setting $exclude_disabled to false has no effect in %s on line %d +Deprecated: get_defined_functions(): The $exclude_disabled parameter has no effect since PHP 8.0 in %s on line %d bool(false) + +Deprecated: get_defined_functions(): The $exclude_disabled parameter has no effect since PHP 8.0 in %s on line %d bool(false) diff --git a/tests/basic/gh17951_ini_parse_1.phpt b/tests/basic/gh17951_ini_parse_1.phpt new file mode 100644 index 0000000000000..fe0dea138e4b2 --- /dev/null +++ b/tests/basic/gh17951_ini_parse_1.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-17951 INI Parse 1 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=128M +max_memory_limit=-1 +--FILE-- + +--EXPECT-- +-1 +128M diff --git a/tests/basic/gh17951_ini_parse_2.phpt b/tests/basic/gh17951_ini_parse_2.phpt new file mode 100644 index 0000000000000..e0f290f4c2cf0 --- /dev/null +++ b/tests/basic/gh17951_ini_parse_2.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-17951 INI Parse 2 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=-1 +max_memory_limit=-1 +--FILE-- + +--EXPECT-- +-1 +-1 diff --git a/tests/basic/gh17951_ini_parse_3.phpt b/tests/basic/gh17951_ini_parse_3.phpt new file mode 100644 index 0000000000000..5057671418621 --- /dev/null +++ b/tests/basic/gh17951_ini_parse_3.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-17951 INI Parse 3 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=128M +max_memory_limit=256M +--FILE-- + +--EXPECT-- +256M +128M diff --git a/tests/basic/gh17951_ini_parse_4.phpt b/tests/basic/gh17951_ini_parse_4.phpt new file mode 100644 index 0000000000000..5690a133d7755 --- /dev/null +++ b/tests/basic/gh17951_ini_parse_4.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-17951 INI Parse 4 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=-1 +max_memory_limit=128M +--FILE-- + +--EXPECT-- +128M +128M diff --git a/tests/basic/gh17951_ini_parse_5.phpt b/tests/basic/gh17951_ini_parse_5.phpt new file mode 100644 index 0000000000000..20e414526000a --- /dev/null +++ b/tests/basic/gh17951_ini_parse_5.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-17951 INI Parse 5 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=256M +max_memory_limit=128M +--FILE-- + +--EXPECT-- +Warning: Failed to set memory_limit to 268435456 bytes. Setting to max_memory_limit instead (currently: 134217728 bytes) in Unknown on line 0 +128M +128M diff --git a/tests/basic/gh17951_runtime_change_1.phpt b/tests/basic/gh17951_runtime_change_1.phpt new file mode 100644 index 0000000000000..12b7b746f2b7a --- /dev/null +++ b/tests/basic/gh17951_runtime_change_1.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-17951 Runtime Change 1 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=128M +max_memory_limit=512M +--FILE-- + +--EXPECT-- +256M diff --git a/tests/basic/gh17951_runtime_change_2.phpt b/tests/basic/gh17951_runtime_change_2.phpt new file mode 100644 index 0000000000000..8bcc5ea65dd5c --- /dev/null +++ b/tests/basic/gh17951_runtime_change_2.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-17951 Runtime Change 2 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=128M +max_memory_limit=512M +--FILE-- + +--EXPECT-- +512M diff --git a/tests/basic/gh17951_runtime_change_3.phpt b/tests/basic/gh17951_runtime_change_3.phpt new file mode 100644 index 0000000000000..975caad4ff0bf --- /dev/null +++ b/tests/basic/gh17951_runtime_change_3.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-17951 Runtime Change 3 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=128M +max_memory_limit=512M +--FILE-- + +--EXPECTF-- +Warning: Failed to set memory_limit to 1073741824 bytes. Setting to max_memory_limit instead (currently: 536870912 bytes) in %s on line %d +512M diff --git a/tests/basic/gh17951_runtime_change_4.phpt b/tests/basic/gh17951_runtime_change_4.phpt new file mode 100644 index 0000000000000..3b27e2c91a9ab --- /dev/null +++ b/tests/basic/gh17951_runtime_change_4.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-17951 Runtime Change 4 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=128M +max_memory_limit=512M +--FILE-- + +--EXPECT-- +512M diff --git a/tests/basic/gh17951_runtime_change_5.phpt b/tests/basic/gh17951_runtime_change_5.phpt new file mode 100644 index 0000000000000..f5f5afd601476 --- /dev/null +++ b/tests/basic/gh17951_runtime_change_5.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-17951 Runtime Change 5 +--CREDITS-- +Frederik Milling Pytlick (frederikpyt@protonmail.com) +--INI-- +memory_limit=128M +max_memory_limit=512M +--FILE-- + +--EXPECT-- +bool(false) +bool(false) +bool(false) +bool(false) diff --git a/tests/basic/ini_directive_deprecated_report_memleaks.phpt b/tests/basic/ini_directive_deprecated_report_memleaks.phpt new file mode 100644 index 0000000000000..961726b499e72 --- /dev/null +++ b/tests/basic/ini_directive_deprecated_report_memleaks.phpt @@ -0,0 +1,11 @@ +--TEST-- +Deprecated INI directive report_memleaks warning +--INI-- +report_memleaks=0 +--FILE-- + +--EXPECT-- +Deprecated: PHP Startup: Directive 'report_memleaks' is deprecated in Unknown on line 0 +Testing deprecated report_memleaks INI directive. diff --git a/tests/basic/timeout_variation_0.phpt b/tests/basic/timeout_variation_0.phpt index ac514e1f9a428..d336eab9072ca 100644 --- a/tests/basic/timeout_variation_0.phpt +++ b/tests/basic/timeout_variation_0.phpt @@ -2,6 +2,9 @@ Timeout within while loop --SKIPIF-- --FILE-- diff --git a/tests/basic/timeout_variation_7.phpt b/tests/basic/timeout_variation_7.phpt index 0401240ba953d..3d40b540677db 100644 --- a/tests/basic/timeout_variation_7.phpt +++ b/tests/basic/timeout_variation_7.phpt @@ -2,6 +2,9 @@ Timeout within for loop --SKIPIF-- --FILE-- diff --git a/tests/classes/bug26737.phpt b/tests/classes/bug26737.phpt index ea7ae1ed9a1cc..230422fc07462 100644 --- a/tests/classes/bug26737.phpt +++ b/tests/classes/bug26737.phpt @@ -18,5 +18,7 @@ $data = serialize($foo); var_dump(str_replace("\0", '\0', $data)); ?> --EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d + Warning: serialize(): "no_such" returned as member variable from __sleep() but does not exist in %s on line %d string(114) "O:3:"foo":3:{s:12:"\0foo\0private";s:7:"private";s:12:"\0*\0protected";s:9:"protected";s:6:"public";s:6:"public";}" diff --git a/tests/classes/factory_and_singleton_007.phpt b/tests/classes/factory_and_singleton_007.phpt index fc232bdb8655a..6cf120e18befa 100644 --- a/tests/classes/factory_and_singleton_007.phpt +++ b/tests/classes/factory_and_singleton_007.phpt @@ -17,4 +17,4 @@ try { ?> --EXPECT-- -Error: Call to protected test::__clone() from global scope +Error: Call to protected method test::__clone() from global scope diff --git a/tests/classes/factory_and_singleton_008.phpt b/tests/classes/factory_and_singleton_008.phpt index 672c083270730..a23af647592f5 100644 --- a/tests/classes/factory_and_singleton_008.phpt +++ b/tests/classes/factory_and_singleton_008.phpt @@ -17,4 +17,4 @@ try { ?> --EXPECT-- -Error: Call to private test::__clone() from global scope +Error: Call to private method test::__clone() from global scope diff --git a/tests/classes/private_members_serialization.phpt b/tests/classes/private_members_serialization.phpt index 1b04b6f59c723..2a4039411b0c5 100644 --- a/tests/classes/private_members_serialization.phpt +++ b/tests/classes/private_members_serialization.phpt @@ -19,5 +19,6 @@ class bar extends foo var_dump(str_replace("\0", '\0', serialize(new bar()))); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d string(114) "O:3:"bar":3:{s:12:"\0foo\0private";s:7:"private";s:12:"\0*\0protected";s:9:"protected";s:6:"public";s:6:"public";}" diff --git a/tests/func/005a.phpt b/tests/func/005a.phpt index cf1e5713770a9..2f527d773adbe 100644 --- a/tests/func/005a.phpt +++ b/tests/func/005a.phpt @@ -2,6 +2,9 @@ Testing register_shutdown_function() with timeout. (Bug: #21513) --SKIPIF-- --FILE-- diff --git a/tests/lang/033.phpt b/tests/lang/033.phpt index e6254d687b07c..41424e40489d6 100644 --- a/tests/lang/033.phpt +++ b/tests/lang/033.phpt @@ -37,7 +37,8 @@ switch ($a): break; endswitch; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Case statements followed by a semicolon (;) are deprecated, use a colon (:) instead in %s If: 11 While: 12346789 For: 0123401234 diff --git a/tests/lang/bug26696.phpt b/tests/lang/bug26696.phpt index 1d10297b12c3d..de0dc90ca0d42 100644 --- a/tests/lang/bug26696.phpt +++ b/tests/lang/bug26696.phpt @@ -15,7 +15,7 @@ for ($i = 0; $i < $len; $i++) { $str = '*'; switch ($str[0]) { - case '*'; + case '*': echo "OK\n"; break; default: diff --git a/tests/lang/bug45392.phpt b/tests/lang/bug45392.phpt index 27e3e994b64d9..cfb09437bd2cc 100644 --- a/tests/lang/bug45392.phpt +++ b/tests/lang/bug45392.phpt @@ -2,6 +2,9 @@ Bug #45392 (ob_start()/ob_end_clean() and memory_limit) --SKIPIF-- E::f [6] => E::g [7] => E::__invoke - [8] => Closure::__invoke + [8] => {closure:%s:%d} ) Array ( - [name] => Closure::__invoke + [name] => {closure:%s:%d} [type] => 1 [flags] => 20593 [level] => 8 @@ -161,7 +161,7 @@ Array [8] => Array ( - [name] => Closure::__invoke + [name] => {closure:%s:%d} [type] => 1 [flags] => 20593 [level] => 8 diff --git a/tests/output/ob_start_basic_002.phpt b/tests/output/ob_start_basic_002.phpt index 700dab5d3c381..e9af2b5e1904c 100644 --- a/tests/output/ob_start_basic_002.phpt +++ b/tests/output/ob_start_basic_002.phpt @@ -35,19 +35,24 @@ foreach ($callbacks as $callback) { } ?> ---EXPECT-- +--EXPECTF-- --> Use callback 'return_empty_string': --> Use callback 'return_false': + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s on line %d My output. --> Use callback 'return_null': +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s on line %d + --> Use callback 'return_string': I stole your output. --> Use callback 'return_zero': -0 +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s on line %d +0 diff --git a/tests/output/ob_start_callback_bad_return/exception_handler.phpt b/tests/output/ob_start_callback_bad_return/exception_handler.phpt new file mode 100644 index 0000000000000..eef3fccc77ec0 --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/exception_handler.phpt @@ -0,0 +1,147 @@ +--TEST-- +ob_start(): Check behaviour with deprecation converted to exception [bad return] +--FILE-- +val; + } +} + +$log = []; + +set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) { + throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); +}); + +function return_null($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return null; +} + +function return_false($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return false; +} + +function return_true($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return true; +} + +function return_zero($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return 0; +} + +function return_non_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return new NotStringable($string); +} + +function return_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return new IsStringable($string); +} + +$cases = [ + 'return_null', + 'return_false', + 'return_true', + 'return_zero', + 'return_non_stringable', + 'return_stringable', +]; +foreach ($cases as $case) { + $log = []; + echo "\n\nTesting: $case\n"; + ob_start($case); + echo "Inside of $case\n"; + try { + ob_end_flush(); + } catch (\ErrorException $e) { + echo $e . "\n"; + } + echo "\nEnd of $case, log was:\n"; + echo implode("\n", $log); +} + +?> +--EXPECTF-- +Testing: return_null +ErrorException: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_null, log was: +return_null: <<>> + +Testing: return_false +Inside of return_false +ErrorException: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_false, log was: +return_false: <<>> + +Testing: return_true +ErrorException: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_true, log was: +return_true: <<>> + +Testing: return_zero +0ErrorException: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_zero, log was: +return_zero: <<>> + +Testing: return_non_stringable +ErrorException: ob_end_flush(): Returning a non-string result from user output handler return_non_stringable is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 69) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_non_stringable, log was: +return_non_stringable: <<>> + +Testing: return_stringable +ErrorException: ob_end_flush(): Returning a non-string result from user output handler return_stringable is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 69) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_stringable, log was: +return_stringable: <<>> diff --git a/tests/output/ob_start_callback_bad_return/exception_handler_nested.phpt b/tests/output/ob_start_callback_bad_return/exception_handler_nested.phpt new file mode 100644 index 0000000000000..64d7f805687b2 --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/exception_handler_nested.phpt @@ -0,0 +1,143 @@ +--TEST-- +ob_start(): Check behaviour with nested deprecation converted to exception [bad return] +--FILE-- +val; + } +} + +$log = []; + +set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) { + throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); +}); + +function return_null($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return null; +} + +function return_false($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return false; +} + +function return_true($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return true; +} + +function return_zero($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return 0; +} + +function return_non_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return new NotStringable($string); +} + +function return_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return new IsStringable($string); +} + +ob_start('return_null'); +ob_start('return_false'); +ob_start('return_true'); +ob_start('return_zero'); +ob_start('return_non_stringable'); +ob_start('return_stringable'); + +echo "In all of them\n\n"; +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_stringable handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_non_stringable handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_zero handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_true handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_false handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_null handler\n\n"; + +echo "All handlers are over\n\n"; +echo implode("\n", $log); + +?> +--EXPECT-- +ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated +Ended return_null handler + +All handlers are over + +return_stringable: <<>> +return_non_stringable: <<>> +return_zero: <<>> +return_true: <<<0ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated +Ended return_zero handler + +>>> +return_false: <<>> +return_null: <<>> diff --git a/tests/output/ob_start_callback_bad_return/handler_false_removed.phpt b/tests/output/ob_start_callback_bad_return/handler_false_removed.phpt new file mode 100644 index 0000000000000..32702a58fcc14 --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/handler_false_removed.phpt @@ -0,0 +1,23 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns false) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_bad_return/handler_is_stringable_removed.phpt b/tests/output/ob_start_callback_bad_return/handler_is_stringable_removed.phpt new file mode 100644 index 0000000000000..0d87358da1b9d --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/handler_is_stringable_removed.phpt @@ -0,0 +1,30 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns stringable object) +--INI-- +memory_limit=2M +--FILE-- +val; + } +} + +ob_start(function() { + // We are out of memory, now trigger a deprecation + return new IsStringable(""); +}); + +$a = []; +// trigger OOM in a resize operation +while (1) { + $a[] = 1; +} + +?> +--EXPECTF-- +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_bad_return/handler_non_stringable_removed.phpt b/tests/output/ob_start_callback_bad_return/handler_non_stringable_removed.phpt new file mode 100644 index 0000000000000..65d8ccfbcba61 --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/handler_non_stringable_removed.phpt @@ -0,0 +1,32 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns non-stringable object) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d + +Fatal error: Uncaught Error: Object of class NotStringable could not be converted to string in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/tests/output/ob_start_callback_bad_return/handler_true_removed.phpt b/tests/output/ob_start_callback_bad_return/handler_true_removed.phpt new file mode 100644 index 0000000000000..5ad19826c4ac7 --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/handler_true_removed.phpt @@ -0,0 +1,23 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns true) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_bad_return/handler_zero_removed.phpt b/tests/output/ob_start_callback_bad_return/handler_zero_removed.phpt new file mode 100644 index 0000000000000..1bc7279c71d35 --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/handler_zero_removed.phpt @@ -0,0 +1,23 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns zero) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_bad_return/multiple_handlers.phpt b/tests/output/ob_start_callback_bad_return/multiple_handlers.phpt new file mode 100644 index 0000000000000..100abe7d79d18 --- /dev/null +++ b/tests/output/ob_start_callback_bad_return/multiple_handlers.phpt @@ -0,0 +1,106 @@ +--TEST-- +ob_start(): Check behaviour with multiple nested handlers with bad return values +--FILE-- +>>"; + return $string; +} + +function return_empty_string($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return ""; +} + +function return_false($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return false; +} + +function return_true($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return true; +} + +function return_null($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return null; +} + +function return_string($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return "I stole your output."; +} + +function return_zero($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + return 0; +} + +ob_start('return_given_string'); +ob_start('return_empty_string'); +ob_start('return_false'); +ob_start('return_true'); +ob_start('return_null'); +ob_start('return_string'); +ob_start('return_zero'); + +echo "Testing..."; + +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); + +echo "\n\nLog:\n"; +echo implode("\n", $log); +?> +--EXPECTF-- +Deprecated: ob_end_flush(): Producing output from user output handler return_given_string is deprecated in %s on line %d3 + +Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d2 + + +Log: +return_zero: <<>> +return_string: <<< +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s on line %d +0>>> +return_null: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_string is deprecated in %s on line %d +I stole your output.>>> +return_true: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_null is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s on line %d +>>> +return_false: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d +>>> +return_empty_string: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_false is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d +>>> +return_given_string: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d2 +>>> diff --git a/tests/output/ob_start_callback_output/exception_handler.phpt b/tests/output/ob_start_callback_output/exception_handler.phpt new file mode 100644 index 0000000000000..2049afc81ef75 --- /dev/null +++ b/tests/output/ob_start_callback_output/exception_handler.phpt @@ -0,0 +1,88 @@ +--TEST-- +ob_start(): Check behaviour with deprecation converted to exception [produce output] +--FILE-- +>>"; + echo __FUNCTION__; + return "FIRST\n"; +} + +function second_handler($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return "SECOND\n"; +} + +function third_handler($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return "THIRD\n"; +} + +$cases = [ + 'first_handler', + 'second_handler', + 'third_handler', +]; +foreach ($cases as $case) { + $log = []; + echo "\n\nTesting: $case\n"; + ob_start($case); + echo "Inside of $case\n"; + try { + ob_end_flush(); + } catch (\ErrorException $e) { + echo $e . "\n"; + } + echo "\nEnd of $case, log was:\n"; + echo implode("\n", $log); +} + +?> +--EXPECTF-- +Testing: first_handler +FIRST +ErrorException: ob_end_flush(): Producing output from user output handler first_handler is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 41) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of first_handler, log was: +first_handler: <<>> + +Testing: second_handler +SECOND +ErrorException: ob_end_flush(): Producing output from user output handler second_handler is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 41) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of second_handler, log was: +second_handler: <<>> + +Testing: third_handler +THIRD +ErrorException: ob_end_flush(): Producing output from user output handler third_handler is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 41) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of third_handler, log was: +third_handler: <<>> diff --git a/tests/output/ob_start_callback_output/exception_handler_nested.phpt b/tests/output/ob_start_callback_output/exception_handler_nested.phpt new file mode 100644 index 0000000000000..562abd63aa632 --- /dev/null +++ b/tests/output/ob_start_callback_output/exception_handler_nested.phpt @@ -0,0 +1,82 @@ +--TEST-- +ob_start(): Check behaviour with nested deprecation converted to exception [produce output] +--FILE-- +>>"; + echo __FUNCTION__; + return "FIRST\n"; +} + +function second_handler($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return "SECOND\n"; +} + +function third_handler($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return "THIRD\n"; +} + +ob_start('first_handler'); +ob_start('second_handler'); +ob_start('third_handler'); + +echo "In all of them\n\n"; +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended third_handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended second_handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended first_handler handler\n\n"; + +echo "All handlers are over\n\n"; +echo implode("\n", $log); + +?> +--EXPECT-- +FIRST +ob_end_flush(): Producing output from user output handler first_handler is deprecated +Ended first_handler handler + +All handlers are over + +third_handler: <<>> +second_handler: <<>> +first_handler: <<>> diff --git a/tests/output/ob_start_callback_output/functions_that_output.phpt b/tests/output/ob_start_callback_output/functions_that_output.phpt new file mode 100644 index 0000000000000..353a7d9752bd7 --- /dev/null +++ b/tests/output/ob_start_callback_output/functions_that_output.phpt @@ -0,0 +1,84 @@ +--TEST-- +ob_start(): Check behaviour with functions that trigger output (nested) +--FILE-- +>>"; + echo __FUNCTION__; + return "echo\n"; +} + +function handle_var_dump($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + var_dump(__FUNCTION__); + return "var_dump\n"; +} + +function handle_var_export($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + var_export(__FUNCTION__); + return "var_export\n"; +} + +function handle_phpcredits($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + phpcredits(); + return "phpcredits\n"; +} + +$cases = [ + 'handle_echo', + 'handle_var_dump', + 'handle_var_export', + 'handle_phpcredits', +]; +foreach ($cases as $case) { + $log = []; + echo "\n\nTesting: $case"; + ob_start($case); + echo "Inside of $case\n"; + ob_end_flush(); + echo "\nEnd of $case, log was:\n"; + echo implode("\n", $log); +} + +?> +--EXPECTF-- +Testing: handle_echo +Deprecated: ob_end_flush(): Producing output from user output handler handle_echo is deprecated in %s on line %d +echo + +End of handle_echo, log was: +handle_echo: <<>> + +Testing: handle_var_dump +Deprecated: ob_end_flush(): Producing output from user output handler handle_var_dump is deprecated in %s on line %d +var_dump + +End of handle_var_dump, log was: +handle_var_dump: <<>> + +Testing: handle_var_export +Deprecated: ob_end_flush(): Producing output from user output handler handle_var_export is deprecated in %s on line %d +var_export + +End of handle_var_export, log was: +handle_var_export: <<>> + +Testing: handle_phpcredits +Deprecated: ob_end_flush(): Producing output from user output handler handle_phpcredits is deprecated in %s on line %d +phpcredits + +End of handle_phpcredits, log was: +handle_phpcredits: <<>> diff --git a/tests/output/ob_start_callback_output/functions_that_output_nested.phpt b/tests/output/ob_start_callback_output/functions_that_output_nested.phpt new file mode 100644 index 0000000000000..976ec46f880b9 --- /dev/null +++ b/tests/output/ob_start_callback_output/functions_that_output_nested.phpt @@ -0,0 +1,69 @@ +--TEST-- +ob_start(): Check behaviour with functions that trigger output (nested) +--FILE-- +>>"; + echo __FUNCTION__; + return "echo\n"; +} + +function handle_var_dump($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + var_dump(__FUNCTION__); + return "var_dump\n"; +} + +function handle_var_export($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + var_export(__FUNCTION__); + return "var_export\n"; +} + +function handle_phpcredits($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + phpcredits(); + return "phpcredits\n"; +} + +ob_start('handle_echo'); +ob_start('handle_var_dump'); +ob_start('handle_var_export'); +ob_start('handle_phpcredits'); + +echo "Testing..."; + +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); + +echo "\n\nLog:\n"; +echo implode("\n", $log); +?> +--EXPECTF-- +Deprecated: ob_end_flush(): Producing output from user output handler handle_echo is deprecated in %s on line %d +echo + + +Log: +handle_phpcredits: <<>> +handle_var_export: <<< +Deprecated: ob_end_flush(): Producing output from user output handler handle_phpcredits is deprecated in %s on line %d +phpcredits +>>> +handle_var_dump: <<< +Deprecated: ob_end_flush(): Producing output from user output handler handle_var_export is deprecated in %s on line %d +var_export +>>> +handle_echo: <<< +Deprecated: ob_end_flush(): Producing output from user output handler handle_var_dump is deprecated in %s on line %d +var_dump +>>> \ No newline at end of file diff --git a/tests/output/ob_start_callback_output/handler_inconsistent_echo.phpt b/tests/output/ob_start_callback_output/handler_inconsistent_echo.phpt new file mode 100644 index 0000000000000..4ab0d9a1f9f27 --- /dev/null +++ b/tests/output/ob_start_callback_output/handler_inconsistent_echo.phpt @@ -0,0 +1,49 @@ +--TEST-- +ob_start(): Check behaviour with handler that doesn't always trigger output +--FILE-- +>>"; + if ($string === "DO ECHO\n") { + echo __FUNCTION__; + } + return $string; +} + +ob_start('handler'); +echo "DO ECHO\n"; +ob_flush(); +echo "NO ECHO\n"; +ob_flush(); +echo "DO ECHO\n"; +ob_flush(); +echo "LAST ONE\n"; +ob_end_flush(); + +echo "\n\nLog:\n"; +echo implode("\n", $log); + +?> +--EXPECTF-- +Deprecated: ob_flush(): Producing output from user output handler handler is deprecated in %s on line %d +DO ECHO +NO ECHO + +Deprecated: ob_flush(): Producing output from user output handler handler is deprecated in %s on line %d +DO ECHO +LAST ONE + + +Log: +handler: <<>> +handler: <<>> +handler: <<>> +handler: <<>> diff --git a/tests/output/ob_start_callback_output/multiple_handlers.phpt b/tests/output/ob_start_callback_output/multiple_handlers.phpt new file mode 100644 index 0000000000000..b951cb22da710 --- /dev/null +++ b/tests/output/ob_start_callback_output/multiple_handlers.phpt @@ -0,0 +1,56 @@ +--TEST-- +ob_start(): Check behaviour with multiple nested handlers with output +--FILE-- +>>"; + echo __FUNCTION__; + return "FIRST\n"; +} + +function second_handler($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return "SECOND\n"; +} + +function third_handler($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return "THIRD\n"; +} + +ob_start('first_handler'); +ob_start('second_handler'); +ob_start('third_handler'); + +echo "Testing..."; + +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); + +echo "\n\nLog:\n"; +echo implode("\n", $log); +?> +--EXPECTF-- +Deprecated: ob_end_flush(): Producing output from user output handler first_handler is deprecated in %s on line %d +FIRST + + +Log: +third_handler: <<>> +second_handler: <<< +Deprecated: ob_end_flush(): Producing output from user output handler third_handler is deprecated in %s on line %d +THIRD +>>> +first_handler: <<< +Deprecated: ob_end_flush(): Producing output from user output handler second_handler is deprecated in %s on line %d +SECOND +>>> diff --git a/tests/output/ob_start_callback_output_and_bad_return/exception_handler.phpt b/tests/output/ob_start_callback_output_and_bad_return/exception_handler.phpt new file mode 100644 index 0000000000000..2b018c792a52c --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/exception_handler.phpt @@ -0,0 +1,153 @@ +--TEST-- +ob_start(): Check behaviour with deprecation converted to exception [bad return + produce output] +--FILE-- +val; + } +} + +$log = []; + +set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) { + throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); +}); + +function return_null($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return null; +} + +function return_false($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return false; +} + +function return_true($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return true; +} + +function return_zero($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return 0; +} + +function return_non_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return new NotStringable($string); +} + +function return_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return new IsStringable($string); +} + +$cases = [ + 'return_null', + 'return_false', + 'return_true', + 'return_zero', + 'return_non_stringable', + 'return_stringable', +]; +foreach ($cases as $case) { + $log = []; + echo "\n\nTesting: $case\n"; + ob_start($case); + echo "Inside of $case\n"; + try { + ob_end_flush(); + } catch (\ErrorException $e) { + echo $e . "\n"; + } + echo "\nEnd of $case, log was:\n"; + echo implode("\n", $log); +} + +?> +--EXPECTF-- +Testing: return_null +ErrorException: ob_end_flush(): Producing output from user output handler return_null is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_null, log was: +return_null: <<>> + +Testing: return_false +Inside of return_false +return_falseErrorException: ob_end_flush(): Producing output from user output handler return_false is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_false, log was: +return_false: <<>> + +Testing: return_true +ErrorException: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_true, log was: +return_true: <<>> + +Testing: return_zero +0ErrorException: ob_end_flush(): Producing output from user output handler return_zero is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_zero, log was: +return_zero: <<>> + +Testing: return_non_stringable +ErrorException: ob_end_flush(): Producing output from user output handler return_non_stringable is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_non_stringable, log was: +return_non_stringable: <<>> + +Testing: return_stringable +ErrorException: ob_end_flush(): Producing output from user output handler return_stringable is deprecated in %s:%d +Stack trace: +#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d) +#1 %s(%d): ob_end_flush() +#2 {main} + +End of return_stringable, log was: +return_stringable: <<>> diff --git a/tests/output/ob_start_callback_output_and_bad_return/exception_handler_nested.phpt b/tests/output/ob_start_callback_output_and_bad_return/exception_handler_nested.phpt new file mode 100644 index 0000000000000..7eb060acc2133 --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/exception_handler_nested.phpt @@ -0,0 +1,149 @@ +--TEST-- +ob_start(): Check behaviour with nested deprecation converted to exception [bad return + produce output] +--FILE-- +val; + } +} + +$log = []; + +set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) { + throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); +}); + +function return_null($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return null; +} + +function return_false($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return false; +} + +function return_true($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return true; +} + +function return_zero($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return 0; +} + +function return_non_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return new NotStringable($string); +} + +function return_stringable($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return new IsStringable($string); +} + +ob_start('return_null'); +ob_start('return_false'); +ob_start('return_true'); +ob_start('return_zero'); +ob_start('return_non_stringable'); +ob_start('return_stringable'); + +echo "In all of them\n\n"; +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_stringable handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_non_stringable handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_zero handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_true handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_false handler\n\n"; + +try { + ob_end_flush(); +} catch (\ErrorException $e) { + echo $e->getMessage() . "\n"; +} +echo "Ended return_null handler\n\n"; + +echo "All handlers are over\n\n"; +echo implode("\n", $log); + +?> +--EXPECT-- +ob_end_flush(): Producing output from user output handler return_null is deprecated +Ended return_null handler + +All handlers are over + +return_stringable: <<>> +return_non_stringable: <<>> +return_zero: <<>> +return_true: <<<0ob_end_flush(): Producing output from user output handler return_zero is deprecated +Ended return_zero handler + +>>> +return_false: <<>> +return_null: <<>> diff --git a/tests/output/ob_start_callback_output_and_bad_return/handler_false_removed.phpt b/tests/output/ob_start_callback_output_and_bad_return/handler_false_removed.phpt new file mode 100644 index 0000000000000..78c736b80cd14 --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/handler_false_removed.phpt @@ -0,0 +1,26 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns false + produces output) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_output_and_bad_return/handler_is_stringable_removed.phpt b/tests/output/ob_start_callback_output_and_bad_return/handler_is_stringable_removed.phpt new file mode 100644 index 0000000000000..9da82bc147e19 --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/handler_is_stringable_removed.phpt @@ -0,0 +1,33 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns stringable object + produces output) +--INI-- +memory_limit=2M +--FILE-- +val; + } +} + +ob_start(function() { + // We are out of memory, now trigger a deprecation + echo "IN HANDLER\n"; + return new IsStringable(""); +}); + +$a = []; +// trigger OOM in a resize operation +while (1) { + $a[] = 1; +} + +?> +--EXPECTF-- +Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_output_and_bad_return/handler_non_stringable_removed.phpt b/tests/output/ob_start_callback_output_and_bad_return/handler_non_stringable_removed.phpt new file mode 100644 index 0000000000000..476acaee9c3a3 --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/handler_non_stringable_removed.phpt @@ -0,0 +1,35 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns non-stringable object + produces output) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d + +Fatal error: Uncaught Error: Object of class NotStringable could not be converted to string in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/tests/output/ob_start_callback_output_and_bad_return/handler_true_removed.phpt b/tests/output/ob_start_callback_output_and_bad_return/handler_true_removed.phpt new file mode 100644 index 0000000000000..2b0218341c9b8 --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/handler_true_removed.phpt @@ -0,0 +1,26 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns true + produces output) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_output_and_bad_return/handler_zero_removed.phpt b/tests/output/ob_start_callback_output_and_bad_return/handler_zero_removed.phpt new file mode 100644 index 0000000000000..8681a846a3648 --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/handler_zero_removed.phpt @@ -0,0 +1,26 @@ +--TEST-- +ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns zero + produces output) +--INI-- +memory_limit=2M +--FILE-- + +--EXPECTF-- +Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d + +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d diff --git a/tests/output/ob_start_callback_output_and_bad_return/multiple_handlers.phpt b/tests/output/ob_start_callback_output_and_bad_return/multiple_handlers.phpt new file mode 100644 index 0000000000000..94d5d34c03830 --- /dev/null +++ b/tests/output/ob_start_callback_output_and_bad_return/multiple_handlers.phpt @@ -0,0 +1,115 @@ +--TEST-- +ob_start(): Check behaviour with multiple nested handlers with bad return values and output +--FILE-- +>>"; + echo __FUNCTION__; + return $string; +} + +function return_empty_string($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return ""; +} + +function return_false($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return false; +} + +function return_true($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return true; +} + +function return_null($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return null; +} + +function return_string($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return "I stole your output."; +} + +function return_zero($string) { + global $log; + $log[] = __FUNCTION__ . ": <<<" . $string . ">>>"; + echo __FUNCTION__; + return 0; +} + +ob_start('return_given_string'); +ob_start('return_empty_string'); +ob_start('return_false'); +ob_start('return_true'); +ob_start('return_null'); +ob_start('return_string'); +ob_start('return_zero'); + +echo "Testing..."; + +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); +ob_end_flush(); + +echo "\n\nLog:\n"; +echo implode("\n", $log); +?> +--EXPECTF-- +Deprecated: ob_end_flush(): Producing output from user output handler return_given_string is deprecated in %s on line %d0 + +Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d9 + + +Log: +return_zero: <<>> +return_string: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_zero is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s on line %d +0>>> +return_null: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_string is deprecated in %s on line %d5 +I stole your output.>>> +return_true: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_null is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s on line %d +>>> +return_false: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d +>>> +return_empty_string: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_false is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d + +Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d +return_false>>> +return_given_string: <<< +Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d9 +>>> diff --git a/tests/run-test/extensions-shared.phpt b/tests/run-test/extensions-shared.phpt index 10ad664d3839b..d4c17f4b09278 100644 --- a/tests/run-test/extensions-shared.phpt +++ b/tests/run-test/extensions-shared.phpt @@ -5,7 +5,7 @@ openssl --SKIPIF--